wip: picker

co-authored-by: nathan <nathan@zed.dev>
co-authored-by: max <max@zed.dev>
This commit is contained in:
Mikayla 2023-11-06 17:09:38 -08:00
parent 3c93b585ab
commit 85000eba81
No known key found for this signature in database
21 changed files with 460 additions and 278 deletions

View file

@ -25,13 +25,13 @@ const TOOLTIP_DELAY: Duration = Duration::from_millis(500);
const TOOLTIP_OFFSET: Point<Pixels> = Point::new(px(10.0), px(8.0));
pub trait StatelessInteractive<V: 'static>: Element<V> {
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V>;
fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V>;
fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
where
Self: Sized,
{
self.stateless_interaction().hover_style = f(StyleRefinement::default());
self.stateless_interactivity().hover_style = f(StyleRefinement::default());
self
}
@ -43,7 +43,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction().group_hover_style = Some(GroupStyle {
self.stateless_interactivity().group_hover_style = Some(GroupStyle {
group: group_name.into(),
style: f(StyleRefinement::default()),
});
@ -58,7 +58,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.mouse_down_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble
@ -79,7 +79,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.mouse_up_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble
@ -100,7 +100,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.mouse_down_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Capture
@ -121,7 +121,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.mouse_up_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Capture
@ -141,7 +141,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.mouse_move_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
@ -158,7 +158,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.scroll_wheel_listeners
.push(Box::new(move |view, event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
@ -174,23 +174,48 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
C: TryInto<DispatchContext>,
C::Error: Debug,
{
self.stateless_interaction().dispatch_context =
self.stateless_interactivity().dispatch_context =
context.try_into().expect("invalid dispatch context");
self
}
fn on_action<A: 'static>(
/// Capture the given action, fires during the capture phase
fn capture_action<A: 'static>(
mut self,
listener: impl Fn(&mut V, &A, DispatchPhase, &mut ViewContext<V>) + 'static,
listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
) -> Self
where
Self: Sized,
{
self.stateless_interaction().key_listeners.push((
self.stateless_interactivity().key_listeners.push((
TypeId::of::<A>(),
Box::new(move |view, event, _, phase, cx| {
let event = event.downcast_ref().unwrap();
listener(view, event, phase, cx);
if phase == DispatchPhase::Capture {
listener(view, event, cx)
}
None
}),
));
self
}
/// Add a listener for the given action, fires during the bubble event phase
fn on_action<A: 'static>(
mut self,
listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
) -> Self
where
Self: Sized,
{
self.stateless_interactivity().key_listeners.push((
TypeId::of::<A>(),
Box::new(move |view, event, _, phase, cx| {
let event = event.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
listener(view, event, cx)
}
None
}),
));
@ -204,7 +229,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction().key_listeners.push((
self.stateless_interactivity().key_listeners.push((
TypeId::of::<KeyDownEvent>(),
Box::new(move |view, event, _, phase, cx| {
let event = event.downcast_ref().unwrap();
@ -222,7 +247,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction().key_listeners.push((
self.stateless_interactivity().key_listeners.push((
TypeId::of::<KeyUpEvent>(),
Box::new(move |view, event, _, phase, cx| {
let event = event.downcast_ref().unwrap();
@ -237,7 +262,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction()
self.stateless_interactivity()
.drag_over_styles
.push((TypeId::of::<S>(), f(StyleRefinement::default())));
self
@ -251,7 +276,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction().group_drag_over_styles.push((
self.stateless_interactivity().group_drag_over_styles.push((
TypeId::of::<S>(),
GroupStyle {
group: group_name.into(),
@ -268,7 +293,7 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
where
Self: Sized,
{
self.stateless_interaction().drop_listeners.push((
self.stateless_interactivity().drop_listeners.push((
TypeId::of::<W>(),
Box::new(move |view, dragged_view, cx| {
listener(view, dragged_view.downcast().unwrap(), cx);
@ -279,13 +304,13 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
}
pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
fn stateful_interaction(&mut self) -> &mut StatefulInteraction<V>;
fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<V>;
fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
where
Self: Sized,
{
self.stateful_interaction().active_style = f(StyleRefinement::default());
self.stateful_interactivity().active_style = f(StyleRefinement::default());
self
}
@ -297,7 +322,7 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
where
Self: Sized,
{
self.stateful_interaction().group_active_style = Some(GroupStyle {
self.stateful_interactivity().group_active_style = Some(GroupStyle {
group: group_name.into(),
style: f(StyleRefinement::default()),
});
@ -311,7 +336,7 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
where
Self: Sized,
{
self.stateful_interaction()
self.stateful_interactivity()
.click_listeners
.push(Box::new(move |view, event, cx| listener(view, event, cx)));
self
@ -326,10 +351,10 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
W: 'static + Render,
{
debug_assert!(
self.stateful_interaction().drag_listener.is_none(),
self.stateful_interactivity().drag_listener.is_none(),
"calling on_drag more than once on the same element is not supported"
);
self.stateful_interaction().drag_listener =
self.stateful_interactivity().drag_listener =
Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
view: listener(view_state, cx).into(),
cursor_offset,
@ -342,10 +367,10 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
Self: Sized,
{
debug_assert!(
self.stateful_interaction().hover_listener.is_none(),
self.stateful_interactivity().hover_listener.is_none(),
"calling on_hover more than once on the same element is not supported"
);
self.stateful_interaction().hover_listener = Some(Box::new(listener));
self.stateful_interactivity().hover_listener = Some(Box::new(listener));
self
}
@ -358,10 +383,10 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
W: 'static + Render,
{
debug_assert!(
self.stateful_interaction().tooltip_builder.is_none(),
self.stateful_interactivity().tooltip_builder.is_none(),
"calling tooltip more than once on the same element is not supported"
);
self.stateful_interaction().tooltip_builder = Some(Arc::new(move |view_state, cx| {
self.stateful_interactivity().tooltip_builder = Some(Arc::new(move |view_state, cx| {
build_tooltip(view_state, cx).into()
}));
@ -369,11 +394,11 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
}
}
pub trait ElementInteraction<V: 'static>: 'static {
fn as_stateless(&self) -> &StatelessInteraction<V>;
fn as_stateless_mut(&mut self) -> &mut StatelessInteraction<V>;
fn as_stateful(&self) -> Option<&StatefulInteraction<V>>;
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteraction<V>>;
pub trait ElementInteractivity<V: 'static>: 'static {
fn as_stateless(&self) -> &StatelessInteractivity<V>;
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V>;
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
fn initialize<R>(
&mut self,
@ -735,11 +760,11 @@ pub trait ElementInteraction<V: 'static>: 'static {
}
#[derive(Deref, DerefMut)]
pub struct StatefulInteraction<V> {
pub struct StatefulInteractivity<V> {
pub id: ElementId,
#[deref]
#[deref_mut]
stateless: StatelessInteraction<V>,
stateless: StatelessInteractivity<V>,
click_listeners: SmallVec<[ClickListener<V>; 2]>,
active_style: StyleRefinement,
group_active_style: Option<GroupStyle>,
@ -748,29 +773,29 @@ pub struct StatefulInteraction<V> {
tooltip_builder: Option<TooltipBuilder<V>>,
}
impl<V: 'static> ElementInteraction<V> for StatefulInteraction<V> {
fn as_stateful(&self) -> Option<&StatefulInteraction<V>> {
impl<V: 'static> ElementInteractivity<V> for StatefulInteractivity<V> {
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
Some(self)
}
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteraction<V>> {
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
Some(self)
}
fn as_stateless(&self) -> &StatelessInteraction<V> {
fn as_stateless(&self) -> &StatelessInteractivity<V> {
&self.stateless
}
fn as_stateless_mut(&mut self) -> &mut StatelessInteraction<V> {
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
&mut self.stateless
}
}
impl<V> From<ElementId> for StatefulInteraction<V> {
impl<V> From<ElementId> for StatefulInteractivity<V> {
fn from(id: ElementId) -> Self {
Self {
id,
stateless: StatelessInteraction::default(),
stateless: StatelessInteractivity::default(),
click_listeners: SmallVec::new(),
drag_listener: None,
hover_listener: None,
@ -783,7 +808,7 @@ impl<V> From<ElementId> for StatefulInteraction<V> {
type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static;
pub struct StatelessInteraction<V> {
pub struct StatelessInteractivity<V> {
pub dispatch_context: DispatchContext,
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
@ -797,9 +822,9 @@ pub struct StatelessInteraction<V> {
drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
}
impl<V> StatelessInteraction<V> {
pub fn into_stateful(self, id: impl Into<ElementId>) -> StatefulInteraction<V> {
StatefulInteraction {
impl<V> StatelessInteractivity<V> {
pub fn into_stateful(self, id: impl Into<ElementId>) -> StatefulInteractivity<V> {
StatefulInteractivity {
id: id.into(),
stateless: self,
click_listeners: SmallVec::new(),
@ -877,7 +902,7 @@ impl InteractiveElementState {
}
}
impl<V> Default for StatelessInteraction<V> {
impl<V> Default for StatelessInteractivity<V> {
fn default() -> Self {
Self {
dispatch_context: DispatchContext::default(),
@ -895,20 +920,20 @@ impl<V> Default for StatelessInteraction<V> {
}
}
impl<V: 'static> ElementInteraction<V> for StatelessInteraction<V> {
fn as_stateful(&self) -> Option<&StatefulInteraction<V>> {
impl<V: 'static> ElementInteractivity<V> for StatelessInteractivity<V> {
fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
None
}
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteraction<V>> {
fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
None
}
fn as_stateless(&self) -> &StatelessInteraction<V> {
fn as_stateless(&self) -> &StatelessInteractivity<V> {
self
}
fn as_stateless_mut(&mut self) -> &mut StatelessInteraction<V> {
fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
self
}
}