1use gpui::Hsla;
2use serde_derive::Deserialize;
3
4use crate::{amber, blue, jade, lime, orange, pink, purple, red};
5
6#[derive(Debug, Clone, Copy, Deserialize, Default)]
7pub struct PlayerColor {
8 pub cursor: Hsla,
9 pub background: Hsla,
10 pub selection: Hsla,
11}
12
13/// A collection of colors that are used to color players in the editor.
14///
15/// The first color is always the local player's color, usually a blue.
16///
17/// The rest of the default colors crisscross back and forth on the
18/// color wheel so that the colors are as distinct as possible.
19#[derive(Clone, Deserialize)]
20pub struct PlayerColors(pub Vec<PlayerColor>);
21
22impl Default for PlayerColors {
23 /// Don't use this!
24 /// We have to have a default to be `[refineable::Refinable]`.
25 /// TODO "Find a way to not need this for Refinable"
26 fn default() -> Self {
27 Self::dark()
28 }
29}
30
31impl PlayerColors {
32 pub fn dark() -> Self {
33 Self(vec![
34 PlayerColor {
35 cursor: blue().dark().step_9(),
36 background: blue().dark().step_5(),
37 selection: blue().dark().step_3(),
38 },
39 PlayerColor {
40 cursor: orange().dark().step_9(),
41 background: orange().dark().step_5(),
42 selection: orange().dark().step_3(),
43 },
44 PlayerColor {
45 cursor: pink().dark().step_9(),
46 background: pink().dark().step_5(),
47 selection: pink().dark().step_3(),
48 },
49 PlayerColor {
50 cursor: lime().dark().step_9(),
51 background: lime().dark().step_5(),
52 selection: lime().dark().step_3(),
53 },
54 PlayerColor {
55 cursor: purple().dark().step_9(),
56 background: purple().dark().step_5(),
57 selection: purple().dark().step_3(),
58 },
59 PlayerColor {
60 cursor: amber().dark().step_9(),
61 background: amber().dark().step_5(),
62 selection: amber().dark().step_3(),
63 },
64 PlayerColor {
65 cursor: jade().dark().step_9(),
66 background: jade().dark().step_5(),
67 selection: jade().dark().step_3(),
68 },
69 PlayerColor {
70 cursor: red().dark().step_9(),
71 background: red().dark().step_5(),
72 selection: red().dark().step_3(),
73 },
74 ])
75 }
76
77 pub fn light() -> Self {
78 Self(vec![
79 PlayerColor {
80 cursor: blue().light().step_9(),
81 background: blue().light().step_4(),
82 selection: blue().light().step_3(),
83 },
84 PlayerColor {
85 cursor: orange().light().step_9(),
86 background: orange().light().step_4(),
87 selection: orange().light().step_3(),
88 },
89 PlayerColor {
90 cursor: pink().light().step_9(),
91 background: pink().light().step_4(),
92 selection: pink().light().step_3(),
93 },
94 PlayerColor {
95 cursor: lime().light().step_9(),
96 background: lime().light().step_4(),
97 selection: lime().light().step_3(),
98 },
99 PlayerColor {
100 cursor: purple().light().step_9(),
101 background: purple().light().step_4(),
102 selection: purple().light().step_3(),
103 },
104 PlayerColor {
105 cursor: amber().light().step_9(),
106 background: amber().light().step_4(),
107 selection: amber().light().step_3(),
108 },
109 PlayerColor {
110 cursor: jade().light().step_9(),
111 background: jade().light().step_4(),
112 selection: jade().light().step_3(),
113 },
114 PlayerColor {
115 cursor: red().light().step_9(),
116 background: red().light().step_4(),
117 selection: red().light().step_3(),
118 },
119 ])
120 }
121}
122
123impl PlayerColors {
124 pub fn local(&self) -> PlayerColor {
125 *self.0.first().unwrap()
126 }
127
128 pub fn absent(&self) -> PlayerColor {
129 *self.0.last().unwrap()
130 }
131
132 pub fn read_only(&self) -> PlayerColor {
133 let local = self.local();
134 PlayerColor {
135 cursor: local.cursor.grayscale(),
136 background: local.background.grayscale(),
137 selection: local.selection.grayscale(),
138 }
139 }
140
141 pub fn color_for_participant(&self, participant_index: u32) -> PlayerColor {
142 let len = self.0.len() - 1;
143 self.0[(participant_index as usize % len) + 1]
144 }
145}