Add group_active

This commit is contained in:
Nathan Sobo 2023-10-11 21:48:21 -06:00
parent d920f7edc1
commit 3dad0d9811
5 changed files with 37 additions and 16 deletions

View file

@ -9,7 +9,7 @@ use smallvec::SmallVec;
#[derive(Default)]
struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
pub fn element_group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
cx.default_global::<GroupBounds>()
.0
.get(name)

View file

@ -1,5 +1,5 @@
use crate::{
element_group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, IdentifiedElement,
group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, IdentifiedElement,
Interactive, MouseEventListeners, MouseMoveEvent, ParentElement, Pixels, SharedString, Styled,
ViewContext,
};
@ -11,7 +11,7 @@ use std::sync::{
};
pub struct Hoverable<E: Styled> {
hover_group: Option<SharedString>,
group: Option<SharedString>,
hovered: Arc<AtomicBool>,
cascade_slot: CascadeSlot,
hovered_style: <E::Style as Refineable>::Refinement,
@ -21,7 +21,7 @@ pub struct Hoverable<E: Styled> {
impl<E: Styled> Hoverable<E> {
pub fn new(mut child: E, hover_group: Option<SharedString>) -> Self {
Self {
hover_group,
group: hover_group,
hovered: Arc::new(AtomicBool::new(false)),
cascade_slot: child.style_cascade().reserve(),
hovered_style: Default::default(),
@ -80,13 +80,13 @@ where
element_state: &mut Self::ElementState,
cx: &mut ViewContext<Self::ViewState>,
) {
let hover_bounds = self
.hover_group
let target_bounds = self
.group
.as_ref()
.and_then(|group| element_group_bounds(group, cx))
.and_then(|group| group_bounds(group, cx))
.unwrap_or(bounds);
let hovered = hover_bounds.contains_point(cx.mouse_position());
let hovered = target_bounds.contains_point(cx.mouse_position());
let slot = self.cascade_slot;
let style = hovered.then_some(self.hovered_style.clone());
@ -98,7 +98,7 @@ where
move |_, event: &MouseMoveEvent, phase, cx| {
if phase == DispatchPhase::Capture {
if hover_bounds.contains_point(event.position) != hovered.load(SeqCst) {
if target_bounds.contains_point(event.position) != hovered.load(SeqCst) {
cx.notify();
}
}

View file

@ -1,6 +1,7 @@
use crate::{
AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive, MouseDownEvent,
MouseEventListeners, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext,
group_bounds, AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive,
MouseDownEvent, MouseEventListeners, MouseUpEvent, ParentElement, Pixels, SharedString, Styled,
ViewContext,
};
use refineable::{Cascade, CascadeSlot, Refineable};
use smallvec::SmallVec;
@ -10,6 +11,7 @@ use std::sync::{
};
pub struct Pressable<E: Styled> {
group: Option<SharedString>,
cascade_slot: CascadeSlot,
pressed_style: <E::Style as Refineable>::Refinement,
child: E,
@ -21,8 +23,9 @@ pub struct PressableState<S> {
}
impl<E: Styled> Pressable<E> {
pub fn new(mut child: E) -> Self {
pub fn new(mut child: E, group: Option<SharedString>) -> Self {
Self {
group,
cascade_slot: child.style_cascade().reserve(),
pressed_style: Default::default(),
child,
@ -96,6 +99,12 @@ where
element_state: &mut Self::ElementState,
cx: &mut ViewContext<Self::ViewState>,
) {
let target_bounds = self
.group
.as_ref()
.and_then(|group| group_bounds(group, cx))
.unwrap_or(bounds);
let style = element_state
.pressed
.load(SeqCst)
@ -105,8 +114,8 @@ where
let pressed = element_state.pressed.clone();
cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, cx| {
if phase == DispatchPhase::Capture {
if bounds.contains_point(event.position) {
if phase == DispatchPhase::Bubble {
if target_bounds.contains_point(event.position) {
pressed.store(true, SeqCst);
cx.notify();
}

View file

@ -34,6 +34,15 @@ pub trait Styled {
Self::Style: 'static + Refineable + Default + Send + Sync,
<Self::Style as Refineable>::Refinement: 'static + Default + Send + Sync,
{
Pressable::new(self)
Pressable::new(self, None)
}
fn group_active(self, group_name: impl Into<SharedString>) -> Pressable<Self>
where
Self: 'static + Sized + Send + Sync,
Self::Style: 'static + Refineable + Default + Send + Sync,
<Self::Style as Refineable>::Refinement: 'static + Default + Send + Sync,
{
Pressable::new(self, Some(group_name.into()))
}
}

View file

@ -175,6 +175,7 @@ impl CollabPanel {
.text_sm()
.child(
div()
.id(0)
// .uri(avatar_uri)
.size_3p5()
.rounded_full()
@ -183,7 +184,9 @@ impl CollabPanel {
.group_hover("")
.fill(theme.middle.negative.default.foreground)
.hover()
.fill(theme.middle.warning.default.foreground),
.fill(theme.middle.warning.default.foreground)
.group_active("")
.fill(theme.middle.accent.default.foreground),
)
.child(label),
)