@@ -10,6 +10,8 @@ use crate::{
pub struct Overlay {
child: ElementBox,
abs_position: Option<Vector2F>,
+ align_to_fit: bool,
+ hoverable: bool,
}
impl Overlay {
@@ -17,6 +19,8 @@ impl Overlay {
Self {
child,
abs_position: None,
+ align_to_fit: false,
+ hoverable: false,
}
}
@@ -24,6 +28,16 @@ impl Overlay {
self.abs_position = Some(position);
self
}
+
+ pub fn align_to_fit(mut self, align_to_fit: bool) -> Self {
+ self.align_to_fit = align_to_fit;
+ self
+ }
+
+ pub fn hoverable(mut self, hoverable: bool) -> Self {
+ self.hoverable = hoverable;
+ self
+ }
}
impl Element for Overlay {
@@ -51,15 +65,30 @@ impl Element for Overlay {
size: &mut Self::LayoutState,
cx: &mut PaintContext,
) {
- let origin = self.abs_position.unwrap_or(bounds.origin());
- let visible_bounds = RectF::new(origin, *size);
+ let mut bounds = RectF::new(self.abs_position.unwrap_or(bounds.origin()), *size);
cx.scene.push_stacking_context(None);
- cx.scene.push_mouse_region(MouseRegion {
- view_id: cx.current_view_id(),
- bounds: visible_bounds,
- ..Default::default()
- });
- self.child.paint(origin, visible_bounds, cx);
+
+ if self.hoverable {
+ cx.scene.push_mouse_region(MouseRegion {
+ view_id: cx.current_view_id(),
+ bounds,
+ ..Default::default()
+ });
+ }
+
+ if self.align_to_fit {
+ // Align overlay to the left if its bounds overflow the window width.
+ if bounds.lower_right().x() > cx.window_size.x() {
+ bounds.set_origin_x(bounds.origin_x() - bounds.width());
+ }
+
+ // Align overlay to the top if its bounds overflow the window height.
+ if bounds.lower_right().y() > cx.window_size.y() {
+ bounds.set_origin_y(bounds.origin_y() - bounds.height());
+ }
+ }
+
+ self.child.paint(bounds.origin(), bounds, cx);
cx.scene.pop_stacking_context();
}
@@ -1,6 +1,6 @@
use super::{
- ContainerStyle, Element, ElementBox, Flex, KeystrokeLabel, MouseEventHandler, ParentElement,
- Text,
+ ContainerStyle, Element, ElementBox, Flex, KeystrokeLabel, MouseEventHandler, Overlay,
+ ParentElement, Text,
};
use crate::{
fonts::TextStyle,
@@ -21,7 +21,7 @@ const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(500);
pub struct Tooltip {
child: ElementBox,
tooltip: Option<ElementBox>,
- state: ElementStateHandle<Rc<TooltipState>>,
+ _state: ElementStateHandle<Rc<TooltipState>>,
}
#[derive(Default)]
@@ -68,15 +68,20 @@ impl Tooltip {
)
.boxed();
Some(
- Self::render_tooltip(text, style, action, false)
- .constrained()
- .dynamically(move |constraint, cx| {
- SizeConstraint::strict_along(
- Axis::Vertical,
- collapsed_tooltip.layout(constraint, cx).y(),
- )
- })
- .boxed(),
+ Overlay::new(
+ Self::render_tooltip(text, style, action, false)
+ .constrained()
+ .dynamically(move |constraint, cx| {
+ SizeConstraint::strict_along(
+ Axis::Vertical,
+ collapsed_tooltip.layout(constraint, cx).y(),
+ )
+ })
+ .boxed(),
+ )
+ .align_to_fit(true)
+ .with_abs_position(state.position.get())
+ .boxed(),
)
} else {
None
@@ -111,7 +116,7 @@ impl Tooltip {
Self {
child,
tooltip,
- state: state_handle,
+ _state: state_handle,
}
}
@@ -171,22 +176,7 @@ impl Element for Tooltip {
) {
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 mut bounds = RectF::new(origin, tooltip.size());
-
- // Align tooltip to the left if its bounds overflow the window width.
- if bounds.lower_right().x() > cx.window_size.x() {
- bounds.set_origin_x(bounds.origin_x() - bounds.width());
- }
-
- // Align tooltip to the top if its bounds overflow the window height.
- if bounds.lower_right().y() > cx.window_size.y() {
- bounds.set_origin_y(bounds.origin_y() - bounds.height());
- }
-
- cx.scene.push_stacking_context(None);
- tooltip.paint(bounds.origin(), bounds, cx);
- cx.scene.pop_stacking_context();
+ tooltip.paint(bounds.origin(), visible_bounds, cx);
}
}