players.rs

  1use gpui::Hsla;
  2
  3#[derive(Debug, Clone, Copy)]
  4pub struct PlayerColor {
  5    pub cursor: Hsla,
  6    pub background: Hsla,
  7    pub selection: Hsla,
  8}
  9
 10/// A collection of colors that are used to color players in the editor.
 11///
 12/// The first color is always the local player's color, usually a blue.
 13///
 14/// The rest of the default colors crisscross back and forth on the
 15/// color wheel so that the colors are as distinct as possible.
 16#[derive(Clone)]
 17pub struct PlayerColors(pub Vec<PlayerColor>);
 18
 19impl PlayerColors {
 20    pub fn local(&self) -> PlayerColor {
 21        // todo!("use a valid color");
 22        *self.0.first().unwrap()
 23    }
 24
 25    pub fn absent(&self) -> PlayerColor {
 26        // todo!("use a valid color");
 27        *self.0.last().unwrap()
 28    }
 29
 30    pub fn color_for_participant(&self, participant_index: u32) -> PlayerColor {
 31        let len = self.0.len() - 1;
 32        self.0[(participant_index as usize % len) + 1]
 33    }
 34}
 35
 36#[cfg(feature = "stories")]
 37pub use stories::*;
 38
 39#[cfg(feature = "stories")]
 40mod stories {
 41    use super::*;
 42    use crate::{ActiveTheme, Story};
 43    use gpui::{div, img, px, Div, ParentElement, Render, Styled, ViewContext};
 44
 45    pub struct PlayerStory;
 46
 47    impl Render for PlayerStory {
 48        type Element = Div<Self>;
 49
 50        fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
 51            Story::container(cx).child(
 52                div()
 53                    .flex()
 54                    .flex_col()
 55                    .gap_4()
 56                    .child(Story::title_for::<_, PlayerColors>(cx))
 57                    .child(Story::label(cx, "Player Colors"))
 58                    .child(
 59                        div()
 60                            .flex()
 61                            .flex_col()
 62                            .gap_1()
 63                            .child(
 64                                div().flex().gap_1().children(
 65                                    cx.theme().players().0.clone().iter_mut().map(|player| {
 66                                        div().w_8().h_8().rounded_md().bg(player.cursor)
 67                                    }),
 68                                ),
 69                            )
 70                            .child(div().flex().gap_1().children(
 71                                cx.theme().players().0.clone().iter_mut().map(|player| {
 72                                    div().w_8().h_8().rounded_md().bg(player.background)
 73                                }),
 74                            ))
 75                            .child(div().flex().gap_1().children(
 76                                cx.theme().players().0.clone().iter_mut().map(|player| {
 77                                    div().w_8().h_8().rounded_md().bg(player.selection)
 78                                }),
 79                            )),
 80                    )
 81                    .child(Story::label(cx, "Avatar Rings"))
 82                    .child(div().flex().gap_1().children(
 83                        cx.theme().players().0.clone().iter_mut().map(|player| {
 84                            div()
 85                                .my_1()
 86                                .rounded_full()
 87                                .border_2()
 88                                .border_color(player.cursor)
 89                                .child(
 90                                    img()
 91                                        .rounded_full()
 92                                        .uri("https://avatars.githubusercontent.com/u/1714999?v=4")
 93                                        .size_6()
 94                                        .bg(gpui::red()),
 95                                )
 96                        }),
 97                    ))
 98                    .child(Story::label(cx, "Player Backgrounds"))
 99                    .child(div().flex().gap_1().children(
100                        cx.theme().players().0.clone().iter_mut().map(|player| {
101                            div()
102                                .my_1()
103                                .rounded_xl()
104                                .flex()
105                                .items_center()
106                                .h_8()
107                                .py_0p5()
108                                .px_1p5()
109                                .bg(player.background)
110                                .child(
111                                div().relative().neg_mx_1().rounded_full().z_index(3)
112                                    .border_2()
113                                    .border_color(player.background)
114                                    .size(px(28.))
115                                    .child(
116                                    img()
117                                        .rounded_full()
118                                        .uri("https://avatars.githubusercontent.com/u/1714999?v=4")
119                                        .size(px(24.))
120                                        .bg(gpui::red()),
121                                ),
122                            ).child(
123                            div().relative().neg_mx_1().rounded_full().z_index(2)
124                                .border_2()
125                                .border_color(player.background)
126                                .size(px(28.))
127                                .child(
128                                img()
129                                    .rounded_full()
130                                    .uri("https://avatars.githubusercontent.com/u/1714999?v=4")
131                                    .size(px(24.))
132                                    .bg(gpui::red()),
133                            ),
134                        ).child(
135                        div().relative().neg_mx_1().rounded_full().z_index(1)
136                            .border_2()
137                            .border_color(player.background)
138                            .size(px(28.))
139                            .child(
140                            img()
141                                .rounded_full()
142                                .uri("https://avatars.githubusercontent.com/u/1714999?v=4")
143                                .size(px(24.))
144                                .bg(gpui::red()),
145                        ),
146                    )
147                        }),
148                    ))
149                    .child(Story::label(cx, "Player Selections"))
150                    .child(div().flex().flex_col().gap_px().children(
151                        cx.theme().players().0.clone().iter_mut().map(|player| {
152                            div()
153                                .flex()
154                                .child(
155                                    div()
156                                        .flex()
157                                        .flex_none()
158                                        .rounded_sm()
159                                        .px_0p5()
160                                        .text_color(cx.theme().colors().text)
161                                        .bg(player.selection)
162                                        .child("The brown fox jumped over the lazy dog."),
163                                )
164                                .child(div().flex_1())
165                        }),
166                    )),
167            )
168        }
169    }
170}