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 theme = theme(cx);
 30
 31        let fill = match (self.window_has_focus, self.color) {
 32            (true, TrafficLightColor::Red) => theme.mac_os_traffic_light_red,
 33            (true, TrafficLightColor::Yellow) => theme.mac_os_traffic_light_yellow,
 34            (true, TrafficLightColor::Green) => theme.mac_os_traffic_light_green,
 35            (false, _) => theme.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        div()
 63            .flex()
 64            .items_center()
 65            .gap_2()
 66            .child(TrafficLight::new(
 67                TrafficLightColor::Red,
 68                self.window_has_focus,
 69            ))
 70            .child(TrafficLight::new(
 71                TrafficLightColor::Yellow,
 72                self.window_has_focus,
 73            ))
 74            .child(TrafficLight::new(
 75                TrafficLightColor::Green,
 76                self.window_has_focus,
 77            ))
 78    }
 79}
 80
 81#[cfg(feature = "stories")]
 82pub use stories::*;
 83
 84#[cfg(feature = "stories")]
 85mod stories {
 86    use crate::Story;
 87
 88    use super::*;
 89
 90    #[derive(Element)]
 91    pub struct TrafficLightsStory<S: 'static + Send + Sync> {
 92        state_type: PhantomData<S>,
 93    }
 94
 95    impl<S: 'static + Send + Sync> TrafficLightsStory<S> {
 96        pub fn new() -> Self {
 97            Self {
 98                state_type: PhantomData,
 99            }
100        }
101
102        fn render(
103            &mut self,
104            _view: &mut S,
105            cx: &mut ViewContext<S>,
106        ) -> impl Element<ViewState = S> {
107            Story::container(cx)
108                .child(Story::title_for::<_, TrafficLights<S>>(cx))
109                .child(Story::label(cx, "Default"))
110                .child(TrafficLights::new())
111                .child(Story::label(cx, "Unfocused"))
112                .child(TrafficLights::new().window_has_focus(false))
113        }
114    }
115}