focus.rs

  1use crate::{FocusEvent, FocusHandle, Interactive, StyleRefinement, ViewContext};
  2use std::sync::Arc;
  3
  4pub trait Focus: Interactive {
  5    fn set_focus_style(&mut self, style: StyleRefinement);
  6    fn set_focus_in_style(&mut self, style: StyleRefinement);
  7    fn set_in_focus_style(&mut self, style: StyleRefinement);
  8    fn handle(&self) -> &FocusHandle;
  9
 10    fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 11    where
 12        Self: Sized,
 13    {
 14        self.set_focus_style(f(StyleRefinement::default()));
 15        self
 16    }
 17
 18    fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 19    where
 20        Self: Sized,
 21    {
 22        self.set_focus_in_style(f(StyleRefinement::default()));
 23        self
 24    }
 25
 26    fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
 27    where
 28        Self: Sized,
 29    {
 30        self.set_in_focus_style(f(StyleRefinement::default()));
 31        self
 32    }
 33
 34    fn on_focus(
 35        mut self,
 36        listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
 37            + Send
 38            + Sync
 39            + 'static,
 40    ) -> Self
 41    where
 42        Self: Sized,
 43    {
 44        let handle = self.handle().clone();
 45        self.listeners()
 46            .focus
 47            .push(Arc::new(move |view, event, cx| {
 48                if event.focused.as_ref() == Some(&handle) {
 49                    listener(view, event, cx)
 50                }
 51            }));
 52        self
 53    }
 54
 55    fn on_blur(
 56        mut self,
 57        listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
 58            + Send
 59            + Sync
 60            + 'static,
 61    ) -> Self
 62    where
 63        Self: Sized,
 64    {
 65        let handle = self.handle().clone();
 66        self.listeners()
 67            .focus
 68            .push(Arc::new(move |view, event, cx| {
 69                if event.blurred.as_ref() == Some(&handle) {
 70                    listener(view, event, cx)
 71                }
 72            }));
 73        self
 74    }
 75
 76    fn on_focus_in(
 77        mut self,
 78        listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
 79            + Send
 80            + Sync
 81            + 'static,
 82    ) -> Self
 83    where
 84        Self: Sized,
 85    {
 86        let handle = self.handle().clone();
 87        self.listeners()
 88            .focus
 89            .push(Arc::new(move |view, event, cx| {
 90                let descendant_blurred = event
 91                    .blurred
 92                    .as_ref()
 93                    .map_or(false, |blurred| handle.contains(blurred, cx));
 94                let descendant_focused = event
 95                    .focused
 96                    .as_ref()
 97                    .map_or(false, |focused| handle.contains(focused, cx));
 98
 99                if !descendant_blurred && descendant_focused {
100                    listener(view, event, cx)
101                }
102            }));
103        self
104    }
105
106    fn on_focus_out(
107        mut self,
108        listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
109            + Send
110            + Sync
111            + 'static,
112    ) -> Self
113    where
114        Self: Sized,
115    {
116        let handle = self.handle().clone();
117        self.listeners()
118            .focus
119            .push(Arc::new(move |view, event, cx| {
120                let descendant_blurred = event
121                    .blurred
122                    .as_ref()
123                    .map_or(false, |blurred| handle.contains(blurred, cx));
124                let descendant_focused = event
125                    .focused
126                    .as_ref()
127                    .map_or(false, |focused| handle.contains(focused, cx));
128                if descendant_blurred && !descendant_focused {
129                    listener(view, event, cx)
130                }
131            }));
132        self
133    }
134}