Detailed changes
@@ -2,40 +2,38 @@ use crate::{
element::{Element, Layout},
layout_context::LayoutContext,
paint_context::PaintContext,
- style::{StyleRefinement, Styleable},
+ style::{Style, StyleHelpers, StyleRefinement, Styleable},
};
use anyhow::Result;
use gpui::platform::MouseMovedEvent;
use refineable::Refineable;
-use std::{cell::Cell, marker::PhantomData};
+use std::cell::Cell;
-pub struct Hoverable<V: 'static, E: Element<V> + Styleable> {
+pub struct Hoverable<E: Styleable> {
hovered: Cell<bool>,
child_style: StyleRefinement,
hovered_style: StyleRefinement,
child: E,
- view_type: PhantomData<V>,
}
-pub fn hoverable<V, E: Element<V> + Styleable>(mut child: E) -> Hoverable<V, E> {
+pub fn hoverable<E: Styleable>(mut child: E) -> Hoverable<E> {
Hoverable {
hovered: Cell::new(false),
child_style: child.declared_style().clone(),
hovered_style: Default::default(),
child,
- view_type: PhantomData,
}
}
-impl<V, E: Element<V> + Styleable> Styleable for Hoverable<V, E> {
+impl<E: Styleable> Styleable for Hoverable<E> {
type Style = E::Style;
fn declared_style(&mut self) -> &mut crate::style::StyleRefinement {
- self.child.declared_style()
+ &mut self.hovered_style
}
}
-impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<V, E> {
+impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<E> {
type Layout = E::Layout;
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, Self::Layout>>
@@ -53,6 +51,10 @@ impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<V, E> {
) where
Self: Sized,
{
+ let bounds = layout.bounds(cx);
+ let order = layout.order(cx);
+
+ self.hovered.set(bounds.contains_point(cx.mouse_position()));
if self.hovered.get() {
// If hovered, refine the child's style with this element's style.
self.child.declared_style().refine(&self.hovered_style);
@@ -61,16 +63,15 @@ impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<V, E> {
*self.child.declared_style() = self.child_style.clone();
}
- let bounds = layout.bounds(cx);
- let order = layout.order(cx);
- self.hovered.set(bounds.contains_point(cx.mouse_position()));
- let was_hovered = self.hovered.clone();
+ let hovered = self.hovered.clone();
cx.on_event(order, move |view, event: &MouseMovedEvent, cx| {
- let is_hovered = bounds.contains_point(event.position);
- if is_hovered != was_hovered.get() {
- was_hovered.set(is_hovered);
+ if bounds.contains_point(event.position) != hovered.get() {
cx.repaint();
}
});
+
+ self.child.paint(view, layout, cx);
}
}
+
+impl<E: Styleable<Style = Style>> StyleHelpers for Hoverable<E> {}
@@ -1,5 +1,8 @@
#![allow(dead_code, unused_variables)]
-use crate::{color::black, style::StyleHelpers};
+use crate::{
+ color::black,
+ style::{StyleHelpers, Styleable},
+};
use element::Element;
use gpui::{
geometry::{rect::RectF, vector::vec2f},
@@ -51,8 +54,8 @@ fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
.h_full()
.w_1_2()
.fill(theme.success(0.5))
- // .hover()
- // .fill(theme.error(0.5))
+ .hoverable()
+ .fill(theme.error(0.5))
// .child(button().label("Hello").click(|_, _, _| println!("click!")))
}
@@ -1,6 +1,7 @@
use crate::{
color::Hsla,
element::{Element, Layout},
+ hoverable::{hoverable, Hoverable},
paint_context::PaintContext,
};
use gpui::{
@@ -255,6 +256,13 @@ pub trait Styleable {
style.refine(self.declared_style());
style
}
+
+ fn hoverable(self) -> Hoverable<Self>
+ where
+ Self: Sized,
+ {
+ hoverable(self)
+ }
}
// Helpers methods that take and return mut self. This includes tailwind style methods for standard sizes etc.
@@ -1363,7 +1363,14 @@ impl AppContext {
window: handle,
}));
- let mut window = Window::new(handle, platform_window, self, build_root_view);
+ let mouse_position = self.platform.mouse_position();
+ let mut window = Window::new(
+ handle,
+ platform_window,
+ mouse_position,
+ self,
+ build_root_view,
+ );
let mut cx = WindowContext::mutable(self, &mut window, handle);
cx.layout(false).expect("initial layout should not error");
let scene = cx.paint().expect("initial paint should not error");
@@ -70,6 +70,7 @@ impl Window {
pub fn new<V, F>(
handle: AnyWindowHandle,
platform_window: Box<dyn platform::Window>,
+ mouse_position: Vector2F,
cx: &mut AppContext,
build_view: F,
) -> Self
@@ -97,7 +98,7 @@ impl Window {
hovered_region_ids: Default::default(),
clicked_region_ids: Default::default(),
clicked_region: None,
- mouse_position: vec2f(0., 0.),
+ mouse_position,
titlebar_height,
appearance,
};
@@ -75,6 +75,7 @@ pub trait Platform: Send + Sync {
fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>>;
fn delete_credentials(&self, url: &str) -> Result<()>;
+ fn mouse_position(&self) -> Vector2F;
fn set_cursor_style(&self, style: CursorStyle);
fn should_auto_hide_scrollbars(&self) -> bool;
@@ -18,7 +18,7 @@ use cocoa::{
},
base::{id, nil, selector, BOOL, YES},
foundation::{
- NSArray, NSAutoreleasePool, NSBundle, NSData, NSInteger, NSProcessInfo, NSString,
+ NSArray, NSAutoreleasePool, NSBundle, NSData, NSInteger, NSPoint, NSProcessInfo, NSString,
NSUInteger, NSURL,
},
};
@@ -37,6 +37,7 @@ use objc::{
runtime::{Class, Object, Sel},
sel, sel_impl,
};
+use pathfinder_geometry::vector::{vec2f, Vector2F};
use postage::oneshot;
use ptr::null_mut;
use std::{
@@ -784,6 +785,11 @@ impl platform::Platform for MacPlatform {
Ok(())
}
+ fn mouse_position(&self) -> Vector2F {
+ let position: NSPoint = unsafe { msg_send![class!(NSEvent), mouseLocation] };
+ vec2f(position.x as f32, position.y as f32)
+ }
+
fn set_cursor_style(&self, style: CursorStyle) {
unsafe {
let new_cursor: id = match style {
@@ -195,6 +195,10 @@ impl super::Platform for Platform {
Ok(())
}
+ fn mouse_position(&self) -> Vector2F {
+ Vector2F::zero()
+ }
+
fn set_cursor_style(&self, style: CursorStyle) {
*self.cursor.lock() = style;
}