traffic_lights.rs

  1use std::marker::PhantomData;
  2
  3use crate::prelude::*;
  4
  5#[derive(Clone, Copy)]
  6enum TrafficLightColor {
  7    Red,
  8    Yellow,
  9    Green,
 10}
 11
 12#[derive(Element)]
 13struct TrafficLight<S: 'static + Send + Sync> {
 14    state_type: PhantomData<S>,
 15    color: TrafficLightColor,
 16    window_has_focus: bool,
 17}
 18
 19impl<S: 'static + Send + Sync> TrafficLight<S> {
 20    fn new(color: TrafficLightColor, window_has_focus: bool) -> Self {
 21        Self {
 22            state_type: PhantomData,
 23            color,
 24            window_has_focus,
 25        }
 26    }
 27
 28    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 29        let color = ThemeColor::new(cx);
 30
 31        let fill = match (self.window_has_focus, self.color) {
 32            (true, TrafficLightColor::Red) => color.mac_os_traffic_light_red,
 33            (true, TrafficLightColor::Yellow) => color.mac_os_traffic_light_yellow,
 34            (true, TrafficLightColor::Green) => color.mac_os_traffic_light_green,
 35            (false, _) => color.filled_element,
 36        };
 37
 38        div().w_3().h_3().rounded_full().bg(fill)
 39    }
 40}
 41
 42#[derive(Element)]
 43pub struct TrafficLights<S: 'static + Send + Sync> {
 44    state_type: PhantomData<S>,
 45    window_has_focus: bool,
 46}
 47
 48impl<S: 'static + Send + Sync> TrafficLights<S> {
 49    pub fn new() -> Self {
 50        Self {
 51            state_type: PhantomData,
 52            window_has_focus: true,
 53        }
 54    }
 55
 56    pub fn window_has_focus(mut self, window_has_focus: bool) -> Self {
 57        self.window_has_focus = window_has_focus;
 58        self
 59    }
 60
 61    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 62        let color = ThemeColor::new(cx);
 63
 64        div()
 65            .flex()
 66            .items_center()
 67            .gap_2()
 68            .child(TrafficLight::new(
 69                TrafficLightColor::Red,
 70                self.window_has_focus,
 71            ))
 72            .child(TrafficLight::new(
 73                TrafficLightColor::Yellow,
 74                self.window_has_focus,
 75            ))
 76            .child(TrafficLight::new(
 77                TrafficLightColor::Green,
 78                self.window_has_focus,
 79            ))
 80    }
 81}
 82
 83#[cfg(feature = "stories")]
 84pub use stories::*;
 85
 86#[cfg(feature = "stories")]
 87mod stories {
 88    use crate::Story;
 89
 90    use super::*;
 91
 92    #[derive(Element)]
 93    pub struct TrafficLightsStory<S: 'static + Send + Sync> {
 94        state_type: PhantomData<S>,
 95    }
 96
 97    impl<S: 'static + Send + Sync> TrafficLightsStory<S> {
 98        pub fn new() -> Self {
 99            Self {
100                state_type: PhantomData,
101            }
102        }
103
104        fn render(
105            &mut self,
106            _view: &mut S,
107            cx: &mut ViewContext<S>,
108        ) -> impl Element<ViewState = S> {
109            Story::container(cx)
110                .child(Story::title_for::<_, TrafficLights<S>>(cx))
111                .child(Story::label(cx, "Default"))
112                .child(TrafficLights::new())
113                .child(Story::label(cx, "Unfocused"))
114                .child(TrafficLights::new().window_has_focus(false))
115        }
116    }
117}