traffic_lights.rs

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