div.rs

   1use crate::{
   2    point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext,
   3    BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle,
   4    IntoElement, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent,
   5    MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent,
   6    SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility,
   7    WindowContext,
   8};
   9use collections::HashMap;
  10use refineable::Refineable;
  11use smallvec::SmallVec;
  12use std::{
  13    any::{Any, TypeId},
  14    cell::RefCell,
  15    fmt::Debug,
  16    mem,
  17    rc::Rc,
  18    time::Duration,
  19};
  20use taffy::style::Overflow;
  21use util::ResultExt;
  22
  23const DRAG_THRESHOLD: f64 = 2.;
  24const TOOLTIP_DELAY: Duration = Duration::from_millis(500);
  25
  26pub struct GroupStyle {
  27    pub group: SharedString,
  28    pub style: StyleRefinement,
  29}
  30
  31pub trait InteractiveElement: Sized + Element {
  32    fn interactivity(&mut self) -> &mut Interactivity;
  33
  34    fn group(mut self, group: impl Into<SharedString>) -> Self {
  35        self.interactivity().group = Some(group.into());
  36        self
  37    }
  38
  39    fn id(mut self, id: impl Into<ElementId>) -> Stateful<Self> {
  40        self.interactivity().element_id = Some(id.into());
  41
  42        Stateful { element: self }
  43    }
  44
  45    fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable<Self> {
  46        self.interactivity().focusable = true;
  47        self.interactivity().tracked_focus_handle = Some(focus_handle.clone());
  48        Focusable { element: self }
  49    }
  50
  51    fn key_context<C, E>(mut self, key_context: C) -> Self
  52    where
  53        C: TryInto<KeyContext, Error = E>,
  54        E: Debug,
  55    {
  56        if let Some(key_context) = key_context.try_into().log_err() {
  57            self.interactivity().key_context = key_context;
  58        }
  59        self
  60    }
  61
  62    fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self {
  63        self.interactivity().hover_style = f(StyleRefinement::default());
  64        self
  65    }
  66
  67    fn group_hover(
  68        mut self,
  69        group_name: impl Into<SharedString>,
  70        f: impl FnOnce(StyleRefinement) -> StyleRefinement,
  71    ) -> Self {
  72        self.interactivity().group_hover_style = Some(GroupStyle {
  73            group: group_name.into(),
  74            style: f(StyleRefinement::default()),
  75        });
  76        self
  77    }
  78
  79    fn on_mouse_down(
  80        mut self,
  81        button: MouseButton,
  82        listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
  83    ) -> Self {
  84        self.interactivity().mouse_down_listeners.push(Box::new(
  85            move |event, bounds, phase, cx| {
  86                if phase == DispatchPhase::Bubble
  87                    && event.button == button
  88                    && bounds.visibly_contains(&event.position, cx)
  89                {
  90                    (listener)(event, cx)
  91                }
  92            },
  93        ));
  94        self
  95    }
  96
  97    fn on_any_mouse_down(
  98        mut self,
  99        listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
 100    ) -> Self {
 101        self.interactivity().mouse_down_listeners.push(Box::new(
 102            move |event, bounds, phase, cx| {
 103                if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) {
 104                    (listener)(event, cx)
 105                }
 106            },
 107        ));
 108        self
 109    }
 110
 111    fn on_mouse_up(
 112        mut self,
 113        button: MouseButton,
 114        listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
 115    ) -> Self {
 116        self.interactivity()
 117            .mouse_up_listeners
 118            .push(Box::new(move |event, bounds, phase, cx| {
 119                if phase == DispatchPhase::Bubble
 120                    && event.button == button
 121                    && bounds.visibly_contains(&event.position, cx)
 122                {
 123                    (listener)(event, cx)
 124                }
 125            }));
 126        self
 127    }
 128
 129    fn on_any_mouse_up(
 130        mut self,
 131        listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
 132    ) -> Self {
 133        self.interactivity()
 134            .mouse_up_listeners
 135            .push(Box::new(move |event, bounds, phase, cx| {
 136                if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) {
 137                    (listener)(event, cx)
 138                }
 139            }));
 140        self
 141    }
 142
 143    fn on_mouse_down_out(
 144        mut self,
 145        listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
 146    ) -> Self {
 147        self.interactivity().mouse_down_listeners.push(Box::new(
 148            move |event, bounds, phase, cx| {
 149                if phase == DispatchPhase::Capture && !bounds.visibly_contains(&event.position, cx)
 150                {
 151                    (listener)(event, cx)
 152                }
 153            },
 154        ));
 155        self
 156    }
 157
 158    fn on_mouse_up_out(
 159        mut self,
 160        button: MouseButton,
 161        listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static,
 162    ) -> Self {
 163        self.interactivity()
 164            .mouse_up_listeners
 165            .push(Box::new(move |event, bounds, phase, cx| {
 166                if phase == DispatchPhase::Capture
 167                    && event.button == button
 168                    && !bounds.visibly_contains(&event.position, cx)
 169                {
 170                    (listener)(event, cx);
 171                }
 172            }));
 173        self
 174    }
 175
 176    fn on_mouse_move(
 177        mut self,
 178        listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static,
 179    ) -> Self {
 180        self.interactivity().mouse_move_listeners.push(Box::new(
 181            move |event, bounds, phase, cx| {
 182                if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) {
 183                    (listener)(event, cx);
 184                }
 185            },
 186        ));
 187        self
 188    }
 189
 190    fn on_scroll_wheel(
 191        mut self,
 192        listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static,
 193    ) -> Self {
 194        self.interactivity().scroll_wheel_listeners.push(Box::new(
 195            move |event, bounds, phase, cx| {
 196                if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) {
 197                    (listener)(event, cx);
 198                }
 199            },
 200        ));
 201        self
 202    }
 203
 204    /// Capture the given action, before normal action dispatch can fire
 205    fn capture_action<A: Action>(
 206        mut self,
 207        listener: impl Fn(&A, &mut WindowContext) + 'static,
 208    ) -> Self {
 209        self.interactivity().action_listeners.push((
 210            TypeId::of::<A>(),
 211            Box::new(move |action, phase, cx| {
 212                let action = action.downcast_ref().unwrap();
 213                if phase == DispatchPhase::Capture {
 214                    (listener)(action, cx)
 215                }
 216            }),
 217        ));
 218        self
 219    }
 220
 221    /// Add a listener for the given action, fires during the bubble event phase
 222    fn on_action<A: Action>(mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) -> Self {
 223        // NOTE: this debug assert has the side-effect of working around
 224        // a bug where a crate consisting only of action definitions does
 225        // not register the actions in debug builds:
 226        //
 227        // https://github.com/rust-lang/rust/issues/47384
 228        // https://github.com/mmastrac/rust-ctor/issues/280
 229        //
 230        // if we are relying on this side-effect still, removing the debug_assert!
 231        // likely breaks the command_palette tests.
 232        // debug_assert!(
 233        //     A::is_registered(),
 234        //     "{:?} is not registered as an action",
 235        //     A::qualified_name()
 236        // );
 237        self.interactivity().action_listeners.push((
 238            TypeId::of::<A>(),
 239            Box::new(move |action, phase, cx| {
 240                let action = action.downcast_ref().unwrap();
 241                if phase == DispatchPhase::Bubble {
 242                    (listener)(action, cx)
 243                }
 244            }),
 245        ));
 246        self
 247    }
 248
 249    fn on_key_down(
 250        mut self,
 251        listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static,
 252    ) -> Self {
 253        self.interactivity()
 254            .key_down_listeners
 255            .push(Box::new(move |event, phase, cx| {
 256                if phase == DispatchPhase::Bubble {
 257                    (listener)(event, cx)
 258                }
 259            }));
 260        self
 261    }
 262
 263    fn capture_key_down(
 264        mut self,
 265        listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static,
 266    ) -> Self {
 267        self.interactivity()
 268            .key_down_listeners
 269            .push(Box::new(move |event, phase, cx| {
 270                if phase == DispatchPhase::Capture {
 271                    listener(event, cx)
 272                }
 273            }));
 274        self
 275    }
 276
 277    fn on_key_up(mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) -> Self {
 278        self.interactivity()
 279            .key_up_listeners
 280            .push(Box::new(move |event, phase, cx| {
 281                if phase == DispatchPhase::Bubble {
 282                    listener(event, cx)
 283                }
 284            }));
 285        self
 286    }
 287
 288    fn capture_key_up(
 289        mut self,
 290        listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static,
 291    ) -> Self {
 292        self.interactivity()
 293            .key_up_listeners
 294            .push(Box::new(move |event, phase, cx| {
 295                if phase == DispatchPhase::Capture {
 296                    listener(event, cx)
 297                }
 298            }));
 299        self
 300    }
 301
 302    fn drag_over<S: 'static>(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self {
 303        self.interactivity()
 304            .drag_over_styles
 305            .push((TypeId::of::<S>(), f(StyleRefinement::default())));
 306        self
 307    }
 308
 309    fn group_drag_over<S: 'static>(
 310        mut self,
 311        group_name: impl Into<SharedString>,
 312        f: impl FnOnce(StyleRefinement) -> StyleRefinement,
 313    ) -> Self {
 314        self.interactivity().group_drag_over_styles.push((
 315            TypeId::of::<S>(),
 316            GroupStyle {
 317                group: group_name.into(),
 318                style: f(StyleRefinement::default()),
 319            },
 320        ));
 321        self
 322    }
 323
 324    fn on_drop<W: 'static>(
 325        mut self,
 326        listener: impl Fn(&View<W>, &mut WindowContext) + 'static,
 327    ) -> Self {
 328        self.interactivity().drop_listeners.push((
 329            TypeId::of::<W>(),
 330            Box::new(move |dragged_view, cx| {
 331                listener(&dragged_view.downcast().unwrap(), cx);
 332            }),
 333        ));
 334        self
 335    }
 336}
 337
 338pub trait StatefulInteractiveElement: InteractiveElement {
 339    fn focusable(mut self) -> Focusable<Self> {
 340        self.interactivity().focusable = true;
 341        Focusable { element: self }
 342    }
 343
 344    fn overflow_scroll(mut self) -> Self {
 345        self.interactivity().base_style.overflow.x = Some(Overflow::Scroll);
 346        self.interactivity().base_style.overflow.y = Some(Overflow::Scroll);
 347        self
 348    }
 349
 350    fn overflow_x_scroll(mut self) -> Self {
 351        self.interactivity().base_style.overflow.x = Some(Overflow::Scroll);
 352        self
 353    }
 354
 355    fn overflow_y_scroll(mut self) -> Self {
 356        self.interactivity().base_style.overflow.y = Some(Overflow::Scroll);
 357        self
 358    }
 359
 360    fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 361    where
 362        Self: Sized,
 363    {
 364        self.interactivity().active_style = f(StyleRefinement::default());
 365        self
 366    }
 367
 368    fn group_active(
 369        mut self,
 370        group_name: impl Into<SharedString>,
 371        f: impl FnOnce(StyleRefinement) -> StyleRefinement,
 372    ) -> Self
 373    where
 374        Self: Sized,
 375    {
 376        self.interactivity().group_active_style = Some(GroupStyle {
 377            group: group_name.into(),
 378            style: f(StyleRefinement::default()),
 379        });
 380        self
 381    }
 382
 383    fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self
 384    where
 385        Self: Sized,
 386    {
 387        self.interactivity()
 388            .click_listeners
 389            .push(Box::new(move |event, cx| listener(event, cx)));
 390        self
 391    }
 392
 393    fn on_drag<W>(mut self, listener: impl Fn(&mut WindowContext) -> View<W> + 'static) -> Self
 394    where
 395        Self: Sized,
 396        W: 'static + Render,
 397    {
 398        debug_assert!(
 399            self.interactivity().drag_listener.is_none(),
 400            "calling on_drag more than once on the same element is not supported"
 401        );
 402        self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag {
 403            view: listener(cx).into(),
 404            cursor_offset,
 405        }));
 406        self
 407    }
 408
 409    fn on_hover(mut self, listener: impl Fn(&bool, &mut WindowContext) + 'static) -> Self
 410    where
 411        Self: Sized,
 412    {
 413        debug_assert!(
 414            self.interactivity().hover_listener.is_none(),
 415            "calling on_hover more than once on the same element is not supported"
 416        );
 417        self.interactivity().hover_listener = Some(Box::new(listener));
 418        self
 419    }
 420
 421    fn tooltip(mut self, build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self
 422    where
 423        Self: Sized,
 424    {
 425        debug_assert!(
 426            self.interactivity().tooltip_builder.is_none(),
 427            "calling tooltip more than once on the same element is not supported"
 428        );
 429        self.interactivity().tooltip_builder = Some(Rc::new(build_tooltip));
 430
 431        self
 432    }
 433}
 434
 435pub trait FocusableElement: InteractiveElement {
 436    fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 437    where
 438        Self: Sized,
 439    {
 440        self.interactivity().focus_style = f(StyleRefinement::default());
 441        self
 442    }
 443
 444    fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 445    where
 446        Self: Sized,
 447    {
 448        self.interactivity().in_focus_style = f(StyleRefinement::default());
 449        self
 450    }
 451
 452    fn on_focus(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
 453    where
 454        Self: Sized,
 455    {
 456        self.interactivity()
 457            .focus_listeners
 458            .push(Box::new(move |focus_handle, event, cx| {
 459                if event.focused.as_ref() == Some(focus_handle) {
 460                    listener(event, cx)
 461                }
 462            }));
 463        self
 464    }
 465
 466    fn on_blur(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
 467    where
 468        Self: Sized,
 469    {
 470        self.interactivity()
 471            .focus_listeners
 472            .push(Box::new(move |focus_handle, event, cx| {
 473                if event.blurred.as_ref() == Some(focus_handle) {
 474                    listener(event, cx)
 475                }
 476            }));
 477        self
 478    }
 479
 480    fn on_focus_in(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
 481    where
 482        Self: Sized,
 483    {
 484        self.interactivity()
 485            .focus_listeners
 486            .push(Box::new(move |focus_handle, event, cx| {
 487                let descendant_blurred = event
 488                    .blurred
 489                    .as_ref()
 490                    .map_or(false, |blurred| focus_handle.contains(blurred, cx));
 491                let descendant_focused = event
 492                    .focused
 493                    .as_ref()
 494                    .map_or(false, |focused| focus_handle.contains(focused, cx));
 495
 496                if !descendant_blurred && descendant_focused {
 497                    listener(event, cx)
 498                }
 499            }));
 500        self
 501    }
 502
 503    fn on_focus_out(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self
 504    where
 505        Self: Sized,
 506    {
 507        self.interactivity()
 508            .focus_listeners
 509            .push(Box::new(move |focus_handle, event, cx| {
 510                let descendant_blurred = event
 511                    .blurred
 512                    .as_ref()
 513                    .map_or(false, |blurred| focus_handle.contains(blurred, cx));
 514                let descendant_focused = event
 515                    .focused
 516                    .as_ref()
 517                    .map_or(false, |focused| focus_handle.contains(focused, cx));
 518                if descendant_blurred && !descendant_focused {
 519                    listener(event, cx)
 520                }
 521            }));
 522        self
 523    }
 524}
 525
 526pub type FocusListeners = SmallVec<[FocusListener; 2]>;
 527
 528pub type FocusListener = Box<dyn Fn(&FocusHandle, &FocusEvent, &mut WindowContext) + 'static>;
 529
 530pub type MouseDownListener =
 531    Box<dyn Fn(&MouseDownEvent, &InteractiveBounds, DispatchPhase, &mut WindowContext) + 'static>;
 532pub type MouseUpListener =
 533    Box<dyn Fn(&MouseUpEvent, &InteractiveBounds, DispatchPhase, &mut WindowContext) + 'static>;
 534
 535pub type MouseMoveListener =
 536    Box<dyn Fn(&MouseMoveEvent, &InteractiveBounds, DispatchPhase, &mut WindowContext) + 'static>;
 537
 538pub type ScrollWheelListener =
 539    Box<dyn Fn(&ScrollWheelEvent, &InteractiveBounds, DispatchPhase, &mut WindowContext) + 'static>;
 540
 541pub type ClickListener = Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>;
 542
 543pub type DragListener = Box<dyn Fn(Point<Pixels>, &mut WindowContext) -> AnyDrag + 'static>;
 544
 545type DropListener = dyn Fn(AnyView, &mut WindowContext) + 'static;
 546
 547pub type TooltipBuilder = Rc<dyn Fn(&mut WindowContext) -> AnyView + 'static>;
 548
 549pub type KeyDownListener = Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + 'static>;
 550
 551pub type KeyUpListener = Box<dyn Fn(&KeyUpEvent, DispatchPhase, &mut WindowContext) + 'static>;
 552
 553pub type ActionListener = Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>;
 554
 555pub fn div() -> Div {
 556    Div {
 557        interactivity: Interactivity::default(),
 558        children: SmallVec::default(),
 559    }
 560}
 561
 562pub struct Div {
 563    interactivity: Interactivity,
 564    children: SmallVec<[AnyElement; 2]>,
 565}
 566
 567impl Styled for Div {
 568    fn style(&mut self) -> &mut StyleRefinement {
 569        &mut self.interactivity.base_style
 570    }
 571}
 572
 573impl InteractiveElement for Div {
 574    fn interactivity(&mut self) -> &mut Interactivity {
 575        &mut self.interactivity
 576    }
 577}
 578
 579impl ParentElement for Div {
 580    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
 581        &mut self.children
 582    }
 583}
 584
 585impl Element for Div {
 586    type State = DivState;
 587
 588    fn layout(
 589        &mut self,
 590        element_state: Option<Self::State>,
 591        cx: &mut WindowContext,
 592    ) -> (LayoutId, Self::State) {
 593        let mut child_layout_ids = SmallVec::new();
 594        let mut interactivity = mem::take(&mut self.interactivity);
 595        let (layout_id, interactive_state) = interactivity.layout(
 596            element_state.map(|s| s.interactive_state),
 597            cx,
 598            |style, cx| {
 599                cx.with_text_style(style.text_style().cloned(), |cx| {
 600                    child_layout_ids = self
 601                        .children
 602                        .iter_mut()
 603                        .map(|child| child.layout(cx))
 604                        .collect::<SmallVec<_>>();
 605                    cx.request_layout(&style, child_layout_ids.iter().copied())
 606                })
 607            },
 608        );
 609        self.interactivity = interactivity;
 610        (
 611            layout_id,
 612            DivState {
 613                interactive_state,
 614                child_layout_ids,
 615            },
 616        )
 617    }
 618
 619    fn paint(
 620        self,
 621        bounds: Bounds<Pixels>,
 622        element_state: &mut Self::State,
 623        cx: &mut WindowContext,
 624    ) {
 625        let mut child_min = point(Pixels::MAX, Pixels::MAX);
 626        let mut child_max = Point::default();
 627        let content_size = if element_state.child_layout_ids.is_empty() {
 628            bounds.size
 629        } else {
 630            for child_layout_id in &element_state.child_layout_ids {
 631                let child_bounds = cx.layout_bounds(*child_layout_id);
 632                child_min = child_min.min(&child_bounds.origin);
 633                child_max = child_max.max(&child_bounds.lower_right());
 634            }
 635            (child_max - child_min).into()
 636        };
 637
 638        self.interactivity.paint(
 639            bounds,
 640            content_size,
 641            &mut element_state.interactive_state,
 642            cx,
 643            |style, scroll_offset, cx| {
 644                if style.visibility == Visibility::Hidden {
 645                    return;
 646                }
 647
 648                let z_index = style.z_index.unwrap_or(0);
 649
 650                cx.with_z_index(z_index, |cx| {
 651                    cx.with_z_index(0, |cx| {
 652                        style.paint(bounds, cx);
 653                    });
 654                    cx.with_z_index(1, |cx| {
 655                        cx.with_text_style(style.text_style().cloned(), |cx| {
 656                            cx.with_content_mask(style.overflow_mask(bounds), |cx| {
 657                                cx.with_element_offset(scroll_offset, |cx| {
 658                                    for child in self.children {
 659                                        child.paint(cx);
 660                                    }
 661                                })
 662                            })
 663                        })
 664                    })
 665                })
 666            },
 667        );
 668    }
 669}
 670
 671impl IntoElement for Div {
 672    type Element = Self;
 673
 674    fn element_id(&self) -> Option<ElementId> {
 675        self.interactivity.element_id.clone()
 676    }
 677
 678    fn into_element(self) -> Self::Element {
 679        self
 680    }
 681}
 682
 683pub struct DivState {
 684    child_layout_ids: SmallVec<[LayoutId; 4]>,
 685    interactive_state: InteractiveElementState,
 686}
 687
 688impl DivState {
 689    pub fn is_active(&self) -> bool {
 690        self.interactive_state.pending_mouse_down.borrow().is_some()
 691    }
 692}
 693
 694pub struct Interactivity {
 695    pub element_id: Option<ElementId>,
 696    pub key_context: KeyContext,
 697    pub focusable: bool,
 698    pub tracked_focus_handle: Option<FocusHandle>,
 699    pub focus_listeners: FocusListeners,
 700    pub group: Option<SharedString>,
 701    pub base_style: StyleRefinement,
 702    pub focus_style: StyleRefinement,
 703    pub in_focus_style: StyleRefinement,
 704    pub hover_style: StyleRefinement,
 705    pub group_hover_style: Option<GroupStyle>,
 706    pub active_style: StyleRefinement,
 707    pub group_active_style: Option<GroupStyle>,
 708    pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
 709    pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
 710    pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>,
 711    pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>,
 712    pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>,
 713    pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>,
 714    pub key_down_listeners: SmallVec<[KeyDownListener; 2]>,
 715    pub key_up_listeners: SmallVec<[KeyUpListener; 2]>,
 716    pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>,
 717    pub drop_listeners: SmallVec<[(TypeId, Box<DropListener>); 2]>,
 718    pub click_listeners: SmallVec<[ClickListener; 2]>,
 719    pub drag_listener: Option<DragListener>,
 720    pub hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>,
 721    pub tooltip_builder: Option<TooltipBuilder>,
 722}
 723
 724#[derive(Clone)]
 725pub struct InteractiveBounds {
 726    pub bounds: Bounds<Pixels>,
 727    pub stacking_order: StackingOrder,
 728}
 729
 730impl InteractiveBounds {
 731    pub fn visibly_contains(&self, point: &Point<Pixels>, cx: &WindowContext) -> bool {
 732        self.bounds.contains_point(point) && cx.was_top_layer(&point, &self.stacking_order)
 733    }
 734}
 735
 736impl Interactivity {
 737    pub fn layout(
 738        &mut self,
 739        element_state: Option<InteractiveElementState>,
 740        cx: &mut WindowContext,
 741        f: impl FnOnce(Style, &mut WindowContext) -> LayoutId,
 742    ) -> (LayoutId, InteractiveElementState) {
 743        let mut element_state = element_state.unwrap_or_default();
 744
 745        // Ensure we store a focus handle in our element state if we're focusable.
 746        // If there's an explicit focus handle we're tracking, use that. Otherwise
 747        // create a new handle and store it in the element state, which lives for as
 748        // as frames contain an element with this id.
 749        if self.focusable {
 750            element_state.focus_handle.get_or_insert_with(|| {
 751                self.tracked_focus_handle
 752                    .clone()
 753                    .unwrap_or_else(|| cx.focus_handle())
 754            });
 755        }
 756
 757        let style = self.compute_style(None, &mut element_state, cx);
 758        let layout_id = f(style, cx);
 759        (layout_id, element_state)
 760    }
 761
 762    pub fn paint(
 763        mut self,
 764        bounds: Bounds<Pixels>,
 765        content_size: Size<Pixels>,
 766        element_state: &mut InteractiveElementState,
 767        cx: &mut WindowContext,
 768        f: impl FnOnce(Style, Point<Pixels>, &mut WindowContext),
 769    ) {
 770        let style = self.compute_style(Some(bounds), element_state, cx);
 771
 772        if style
 773            .background
 774            .as_ref()
 775            .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent()))
 776        {
 777            cx.with_z_index(style.z_index.unwrap_or(0), |cx| cx.add_opaque_layer(bounds))
 778        }
 779
 780        let interactive_bounds = Rc::new(InteractiveBounds {
 781            bounds: bounds.intersect(&cx.content_mask().bounds),
 782            stacking_order: cx.stacking_order().clone(),
 783        });
 784
 785        if let Some(mouse_cursor) = style.mouse_cursor {
 786            let mouse_position = &cx.mouse_position();
 787            let hovered = interactive_bounds.visibly_contains(mouse_position, cx);
 788            if hovered {
 789                cx.set_cursor_style(mouse_cursor);
 790            }
 791        }
 792
 793        for listener in self.mouse_down_listeners.drain(..) {
 794            let interactive_bounds = interactive_bounds.clone();
 795            cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
 796                listener(event, &*interactive_bounds, phase, cx);
 797            })
 798        }
 799
 800        for listener in self.mouse_up_listeners.drain(..) {
 801            let interactive_bounds = interactive_bounds.clone();
 802            cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
 803                listener(event, &*interactive_bounds, phase, cx);
 804            })
 805        }
 806
 807        for listener in self.mouse_move_listeners.drain(..) {
 808            let interactive_bounds = interactive_bounds.clone();
 809            cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 810                listener(event, &*interactive_bounds, phase, cx);
 811            })
 812        }
 813
 814        for listener in self.scroll_wheel_listeners.drain(..) {
 815            let interactive_bounds = interactive_bounds.clone();
 816            cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
 817                listener(event, &*interactive_bounds, phase, cx);
 818            })
 819        }
 820
 821        let hover_group_bounds = self
 822            .group_hover_style
 823            .as_ref()
 824            .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
 825
 826        if let Some(group_bounds) = hover_group_bounds {
 827            // todo!() needs cx.was_top_layer
 828            let hovered = group_bounds.contains_point(&cx.mouse_position());
 829            cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 830                if phase == DispatchPhase::Capture {
 831                    if group_bounds.contains_point(&event.position) != hovered {
 832                        cx.notify();
 833                    }
 834                }
 835            });
 836        }
 837
 838        if self.hover_style.is_some()
 839            || (cx.active_drag.is_some() && !self.drag_over_styles.is_empty())
 840        {
 841            let interactive_bounds = interactive_bounds.clone();
 842            let hovered = interactive_bounds.visibly_contains(&cx.mouse_position(), cx);
 843            cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 844                if phase == DispatchPhase::Capture {
 845                    if interactive_bounds.visibly_contains(&event.position, cx) != hovered {
 846                        cx.notify();
 847                    }
 848                }
 849            });
 850        }
 851
 852        if cx.active_drag.is_some() {
 853            let drop_listeners = mem::take(&mut self.drop_listeners);
 854            let interactive_bounds = interactive_bounds.clone();
 855            cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
 856                if phase == DispatchPhase::Bubble
 857                    && interactive_bounds.visibly_contains(&event.position, &cx)
 858                {
 859                    if let Some(drag_state_type) =
 860                        cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
 861                    {
 862                        for (drop_state_type, listener) in &drop_listeners {
 863                            if *drop_state_type == drag_state_type {
 864                                let drag = cx
 865                                    .active_drag
 866                                    .take()
 867                                    .expect("checked for type drag state type above");
 868                                listener(drag.view.clone(), cx);
 869                                cx.notify();
 870                                cx.stop_propagation();
 871                            }
 872                        }
 873                    }
 874                }
 875            });
 876        }
 877
 878        let click_listeners = mem::take(&mut self.click_listeners);
 879        let drag_listener = mem::take(&mut self.drag_listener);
 880
 881        if !click_listeners.is_empty() || drag_listener.is_some() {
 882            let pending_mouse_down = element_state.pending_mouse_down.clone();
 883            let mouse_down = pending_mouse_down.borrow().clone();
 884            if let Some(mouse_down) = mouse_down {
 885                if let Some(drag_listener) = drag_listener {
 886                    let active_state = element_state.clicked_state.clone();
 887                    let interactive_bounds = interactive_bounds.clone();
 888
 889                    cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 890                        if cx.active_drag.is_some() {
 891                            if phase == DispatchPhase::Capture {
 892                                cx.notify();
 893                            }
 894                        } else if phase == DispatchPhase::Bubble
 895                            && interactive_bounds.visibly_contains(&event.position, cx)
 896                            && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD
 897                        {
 898                            *active_state.borrow_mut() = ElementClickedState::default();
 899                            let cursor_offset = event.position - bounds.origin;
 900                            let drag = drag_listener(cursor_offset, cx);
 901                            cx.active_drag = Some(drag);
 902                            cx.notify();
 903                            cx.stop_propagation();
 904                        }
 905                    });
 906                }
 907
 908                let interactive_bounds = interactive_bounds.clone();
 909                cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
 910                    if phase == DispatchPhase::Bubble
 911                        && interactive_bounds.visibly_contains(&event.position, cx)
 912                    {
 913                        let mouse_click = ClickEvent {
 914                            down: mouse_down.clone(),
 915                            up: event.clone(),
 916                        };
 917                        for listener in &click_listeners {
 918                            listener(&mouse_click, cx);
 919                        }
 920                    }
 921                    *pending_mouse_down.borrow_mut() = None;
 922                    cx.notify();
 923                });
 924            } else {
 925                let interactive_bounds = interactive_bounds.clone();
 926                cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
 927                    if phase == DispatchPhase::Bubble
 928                        && interactive_bounds.visibly_contains(&event.position, cx)
 929                    {
 930                        *pending_mouse_down.borrow_mut() = Some(event.clone());
 931                        cx.notify();
 932                    }
 933                });
 934            }
 935        }
 936
 937        if let Some(hover_listener) = self.hover_listener.take() {
 938            let was_hovered = element_state.hover_state.clone();
 939            let has_mouse_down = element_state.pending_mouse_down.clone();
 940            let interactive_bounds = interactive_bounds.clone();
 941
 942            cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 943                if phase != DispatchPhase::Bubble {
 944                    return;
 945                }
 946                let is_hovered = interactive_bounds.visibly_contains(&event.position, cx)
 947                    && has_mouse_down.borrow().is_none();
 948                let mut was_hovered = was_hovered.borrow_mut();
 949
 950                if is_hovered != was_hovered.clone() {
 951                    *was_hovered = is_hovered;
 952                    drop(was_hovered);
 953
 954                    hover_listener(&is_hovered, cx);
 955                }
 956            });
 957        }
 958
 959        if let Some(tooltip_builder) = self.tooltip_builder.take() {
 960            let active_tooltip = element_state.active_tooltip.clone();
 961            let pending_mouse_down = element_state.pending_mouse_down.clone();
 962            let interactive_bounds = interactive_bounds.clone();
 963
 964            cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
 965                if phase != DispatchPhase::Bubble {
 966                    return;
 967                }
 968
 969                let is_hovered = interactive_bounds.visibly_contains(&event.position, cx)
 970                    && pending_mouse_down.borrow().is_none();
 971                if !is_hovered {
 972                    active_tooltip.borrow_mut().take();
 973                    return;
 974                }
 975
 976                if active_tooltip.borrow().is_none() {
 977                    let task = cx.spawn({
 978                        let active_tooltip = active_tooltip.clone();
 979                        let tooltip_builder = tooltip_builder.clone();
 980
 981                        move |mut cx| async move {
 982                            cx.background_executor().timer(TOOLTIP_DELAY).await;
 983                            cx.update(|_, cx| {
 984                                active_tooltip.borrow_mut().replace(ActiveTooltip {
 985                                    tooltip: Some(AnyTooltip {
 986                                        view: tooltip_builder(cx),
 987                                        cursor_offset: cx.mouse_position(),
 988                                    }),
 989                                    _task: None,
 990                                });
 991                                cx.notify();
 992                            })
 993                            .ok();
 994                        }
 995                    });
 996                    active_tooltip.borrow_mut().replace(ActiveTooltip {
 997                        tooltip: None,
 998                        _task: Some(task),
 999                    });
1000                }
1001            });
1002
1003            let active_tooltip = element_state.active_tooltip.clone();
1004            cx.on_mouse_event(move |_: &MouseDownEvent, _, _| {
1005                active_tooltip.borrow_mut().take();
1006            });
1007
1008            if let Some(active_tooltip) = element_state.active_tooltip.borrow().as_ref() {
1009                if active_tooltip.tooltip.is_some() {
1010                    cx.active_tooltip = active_tooltip.tooltip.clone()
1011                }
1012            }
1013        }
1014
1015        let active_state = element_state.clicked_state.clone();
1016        if !active_state.borrow().is_clicked() {
1017            cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| {
1018                if phase == DispatchPhase::Capture {
1019                    *active_state.borrow_mut() = ElementClickedState::default();
1020                    cx.notify();
1021                }
1022            });
1023        } else {
1024            let active_group_bounds = self
1025                .group_active_style
1026                .as_ref()
1027                .and_then(|group_active| GroupBounds::get(&group_active.group, cx));
1028            let interactive_bounds = interactive_bounds.clone();
1029            cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| {
1030                if phase == DispatchPhase::Bubble {
1031                    let group = active_group_bounds
1032                        .map_or(false, |bounds| bounds.contains_point(&down.position));
1033                    let element = interactive_bounds.visibly_contains(&down.position, cx);
1034                    if group || element {
1035                        *active_state.borrow_mut() = ElementClickedState { group, element };
1036                        cx.notify();
1037                    }
1038                }
1039            });
1040        }
1041
1042        let overflow = style.overflow;
1043        if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll {
1044            let scroll_offset = element_state
1045                .scroll_offset
1046                .get_or_insert_with(Rc::default)
1047                .clone();
1048            let line_height = cx.line_height();
1049            let scroll_max = (content_size - bounds.size).max(&Size::default());
1050            let interactive_bounds = interactive_bounds.clone();
1051
1052            cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
1053                if phase == DispatchPhase::Bubble
1054                    && interactive_bounds.visibly_contains(&event.position, cx)
1055                {
1056                    let mut scroll_offset = scroll_offset.borrow_mut();
1057                    let old_scroll_offset = *scroll_offset;
1058                    let delta = event.delta.pixel_delta(line_height);
1059
1060                    if overflow.x == Overflow::Scroll {
1061                        scroll_offset.x =
1062                            (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.));
1063                    }
1064
1065                    if overflow.y == Overflow::Scroll {
1066                        scroll_offset.y =
1067                            (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.));
1068                    }
1069
1070                    if *scroll_offset != old_scroll_offset {
1071                        cx.notify();
1072                        cx.stop_propagation();
1073                    }
1074                }
1075            });
1076        }
1077
1078        if let Some(group) = self.group.clone() {
1079            GroupBounds::push(group, bounds, cx);
1080        }
1081
1082        let scroll_offset = element_state
1083            .scroll_offset
1084            .as_ref()
1085            .map(|scroll_offset| *scroll_offset.borrow());
1086
1087        cx.with_key_dispatch(
1088            self.key_context.clone(),
1089            element_state.focus_handle.clone(),
1090            |_, cx| {
1091                for listener in self.key_down_listeners.drain(..) {
1092                    cx.on_key_event(move |event: &KeyDownEvent, phase, cx| {
1093                        listener(event, phase, cx);
1094                    })
1095                }
1096
1097                for listener in self.key_up_listeners.drain(..) {
1098                    cx.on_key_event(move |event: &KeyUpEvent, phase, cx| {
1099                        listener(event, phase, cx);
1100                    })
1101                }
1102
1103                for (action_type, listener) in self.action_listeners {
1104                    cx.on_action(action_type, listener)
1105                }
1106
1107                if let Some(focus_handle) = element_state.focus_handle.as_ref() {
1108                    for listener in self.focus_listeners {
1109                        let focus_handle = focus_handle.clone();
1110                        cx.on_focus_changed(move |event, cx| listener(&focus_handle, event, cx));
1111                    }
1112                }
1113
1114                f(style, scroll_offset.unwrap_or_default(), cx)
1115            },
1116        );
1117
1118        if let Some(group) = self.group.as_ref() {
1119            GroupBounds::pop(group, cx);
1120        }
1121    }
1122
1123    pub fn compute_style(
1124        &self,
1125        bounds: Option<Bounds<Pixels>>,
1126        element_state: &mut InteractiveElementState,
1127        cx: &mut WindowContext,
1128    ) -> Style {
1129        let mut style = Style::default();
1130        style.refine(&self.base_style);
1131
1132        if let Some(focus_handle) = self.tracked_focus_handle.as_ref() {
1133            if focus_handle.within_focused(cx) {
1134                style.refine(&self.in_focus_style);
1135            }
1136
1137            if focus_handle.is_focused(cx) {
1138                style.refine(&self.focus_style);
1139            }
1140        }
1141
1142        if let Some(bounds) = bounds {
1143            let mouse_position = cx.mouse_position();
1144            if let Some(group_hover) = self.group_hover_style.as_ref() {
1145                if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) {
1146                    if group_bounds.contains_point(&mouse_position) {
1147                        style.refine(&group_hover.style);
1148                    }
1149                }
1150            }
1151            if self.hover_style.is_some() {
1152                if bounds
1153                    .intersect(&cx.content_mask().bounds)
1154                    .contains_point(&mouse_position)
1155                    && cx.was_top_layer(&mouse_position, cx.stacking_order())
1156                {
1157                    style.refine(&self.hover_style);
1158                }
1159            }
1160
1161            if let Some(drag) = cx.active_drag.take() {
1162                for (state_type, group_drag_style) in &self.group_drag_over_styles {
1163                    if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
1164                        if *state_type == drag.view.entity_type()
1165                        // todo!() needs to handle cx.content_mask() and cx.is_top()
1166                            && group_bounds.contains_point(&mouse_position)
1167                        {
1168                            style.refine(&group_drag_style.style);
1169                        }
1170                    }
1171                }
1172
1173                for (state_type, drag_over_style) in &self.drag_over_styles {
1174                    if *state_type == drag.view.entity_type()
1175                        && bounds
1176                            .intersect(&cx.content_mask().bounds)
1177                            .contains_point(&mouse_position)
1178                        && cx.was_top_layer(&mouse_position, cx.stacking_order())
1179                    {
1180                        style.refine(drag_over_style);
1181                    }
1182                }
1183
1184                cx.active_drag = Some(drag);
1185            }
1186        }
1187
1188        let clicked_state = element_state.clicked_state.borrow();
1189        if clicked_state.group {
1190            if let Some(group) = self.group_active_style.as_ref() {
1191                style.refine(&group.style)
1192            }
1193        }
1194
1195        if clicked_state.element {
1196            style.refine(&self.active_style)
1197        }
1198
1199        style
1200    }
1201}
1202
1203impl Default for Interactivity {
1204    fn default() -> Self {
1205        Self {
1206            element_id: None,
1207            key_context: KeyContext::default(),
1208            focusable: false,
1209            tracked_focus_handle: None,
1210            focus_listeners: SmallVec::default(),
1211            // scroll_offset: Point::default(),
1212            group: None,
1213            base_style: StyleRefinement::default(),
1214            focus_style: StyleRefinement::default(),
1215            in_focus_style: StyleRefinement::default(),
1216            hover_style: StyleRefinement::default(),
1217            group_hover_style: None,
1218            active_style: StyleRefinement::default(),
1219            group_active_style: None,
1220            drag_over_styles: SmallVec::new(),
1221            group_drag_over_styles: SmallVec::new(),
1222            mouse_down_listeners: SmallVec::new(),
1223            mouse_up_listeners: SmallVec::new(),
1224            mouse_move_listeners: SmallVec::new(),
1225            scroll_wheel_listeners: SmallVec::new(),
1226            key_down_listeners: SmallVec::new(),
1227            key_up_listeners: SmallVec::new(),
1228            action_listeners: SmallVec::new(),
1229            drop_listeners: SmallVec::new(),
1230            click_listeners: SmallVec::new(),
1231            drag_listener: None,
1232            hover_listener: None,
1233            tooltip_builder: None,
1234        }
1235    }
1236}
1237
1238#[derive(Default)]
1239pub struct InteractiveElementState {
1240    pub focus_handle: Option<FocusHandle>,
1241    pub clicked_state: Rc<RefCell<ElementClickedState>>,
1242    pub hover_state: Rc<RefCell<bool>>,
1243    pub pending_mouse_down: Rc<RefCell<Option<MouseDownEvent>>>,
1244    pub scroll_offset: Option<Rc<RefCell<Point<Pixels>>>>,
1245    pub active_tooltip: Rc<RefCell<Option<ActiveTooltip>>>,
1246}
1247
1248pub struct ActiveTooltip {
1249    tooltip: Option<AnyTooltip>,
1250    _task: Option<Task<()>>,
1251}
1252
1253/// Whether or not the element or a group that contains it is clicked by the mouse.
1254#[derive(Copy, Clone, Default, Eq, PartialEq)]
1255pub struct ElementClickedState {
1256    pub group: bool,
1257    pub element: bool,
1258}
1259
1260impl ElementClickedState {
1261    fn is_clicked(&self) -> bool {
1262        self.group || self.element
1263    }
1264}
1265
1266#[derive(Default)]
1267pub struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
1268
1269impl GroupBounds {
1270    pub fn get(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
1271        cx.default_global::<Self>()
1272            .0
1273            .get(name)
1274            .and_then(|bounds_stack| bounds_stack.last())
1275            .cloned()
1276    }
1277
1278    pub fn push(name: SharedString, bounds: Bounds<Pixels>, cx: &mut AppContext) {
1279        cx.default_global::<Self>()
1280            .0
1281            .entry(name)
1282            .or_default()
1283            .push(bounds);
1284    }
1285
1286    pub fn pop(name: &SharedString, cx: &mut AppContext) {
1287        cx.default_global::<Self>().0.get_mut(name).unwrap().pop();
1288    }
1289}
1290
1291pub struct Focusable<E> {
1292    element: E,
1293}
1294
1295impl<E: InteractiveElement> FocusableElement for Focusable<E> {}
1296
1297impl<E> InteractiveElement for Focusable<E>
1298where
1299    E: InteractiveElement,
1300{
1301    fn interactivity(&mut self) -> &mut Interactivity {
1302        self.element.interactivity()
1303    }
1304}
1305
1306impl<E: StatefulInteractiveElement> StatefulInteractiveElement for Focusable<E> {}
1307
1308impl<E> Styled for Focusable<E>
1309where
1310    E: Styled,
1311{
1312    fn style(&mut self) -> &mut StyleRefinement {
1313        self.element.style()
1314    }
1315}
1316
1317impl<E> Element for Focusable<E>
1318where
1319    E: Element,
1320{
1321    type State = E::State;
1322
1323    fn layout(
1324        &mut self,
1325        state: Option<Self::State>,
1326        cx: &mut WindowContext,
1327    ) -> (LayoutId, Self::State) {
1328        self.element.layout(state, cx)
1329    }
1330
1331    fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
1332        self.element.paint(bounds, state, cx)
1333    }
1334}
1335
1336impl<E> IntoElement for Focusable<E>
1337where
1338    E: Element,
1339{
1340    type Element = E;
1341
1342    fn element_id(&self) -> Option<ElementId> {
1343        self.element.element_id()
1344    }
1345
1346    fn into_element(self) -> Self::Element {
1347        self.element
1348    }
1349}
1350
1351impl<E> ParentElement for Focusable<E>
1352where
1353    E: ParentElement,
1354{
1355    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
1356        self.element.children_mut()
1357    }
1358}
1359
1360pub struct Stateful<E> {
1361    element: E,
1362}
1363
1364impl<E> Styled for Stateful<E>
1365where
1366    E: Styled,
1367{
1368    fn style(&mut self) -> &mut StyleRefinement {
1369        self.element.style()
1370    }
1371}
1372
1373impl<E> StatefulInteractiveElement for Stateful<E>
1374where
1375    E: Element,
1376    Self: InteractiveElement,
1377{
1378}
1379
1380impl<E> InteractiveElement for Stateful<E>
1381where
1382    E: InteractiveElement,
1383{
1384    fn interactivity(&mut self) -> &mut Interactivity {
1385        self.element.interactivity()
1386    }
1387}
1388
1389impl<E: FocusableElement> FocusableElement for Stateful<E> {}
1390
1391impl<E> Element for Stateful<E>
1392where
1393    E: Element,
1394{
1395    type State = E::State;
1396
1397    fn layout(
1398        &mut self,
1399        state: Option<Self::State>,
1400        cx: &mut WindowContext,
1401    ) -> (LayoutId, Self::State) {
1402        self.element.layout(state, cx)
1403    }
1404
1405    fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
1406        self.element.paint(bounds, state, cx)
1407    }
1408}
1409
1410impl<E> IntoElement for Stateful<E>
1411where
1412    E: Element,
1413{
1414    type Element = Self;
1415
1416    fn element_id(&self) -> Option<ElementId> {
1417        self.element.element_id()
1418    }
1419
1420    fn into_element(self) -> Self::Element {
1421        self
1422    }
1423}
1424
1425impl<E> ParentElement for Stateful<E>
1426where
1427    E: ParentElement,
1428{
1429    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
1430        self.element.children_mut()
1431    }
1432}