traffic_lights.rs

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