1pub use gpui3::{
2 div, Element, IntoAnyElement, ParentElement, ScrollState, StyleHelpers, Styled, ViewContext,
3 WindowContext,
4};
5
6pub use crate::{theme, ButtonVariant, ElementExt, Theme};
7
8use gpui3::{hsla, rems, rgb, AbsoluteLength, Hsla};
9use strum::EnumIter;
10
11#[derive(Clone, Copy)]
12pub struct Token {
13 pub list_indent_depth: AbsoluteLength,
14 pub default_panel_size: AbsoluteLength,
15 pub state_hover_background: Hsla,
16 pub state_active_background: Hsla,
17}
18
19impl Default for Token {
20 fn default() -> Self {
21 Self {
22 list_indent_depth: rems(0.3).into(),
23 default_panel_size: AbsoluteLength::Rems(rems(16.)),
24 state_hover_background: hsla(0.0, 0.0, 0.0, 0.08),
25 state_active_background: hsla(0.0, 0.0, 0.0, 0.16),
26 }
27 }
28}
29
30pub fn token() -> Token {
31 Token::default()
32}
33
34#[derive(Default)]
35pub struct SystemColor {
36 pub transparent: Hsla,
37 pub mac_os_traffic_light_red: Hsla,
38 pub mac_os_traffic_light_yellow: Hsla,
39 pub mac_os_traffic_light_green: Hsla,
40}
41
42impl SystemColor {
43 pub fn new() -> SystemColor {
44 SystemColor {
45 transparent: hsla(0.0, 0.0, 0.0, 0.0),
46 mac_os_traffic_light_red: rgb::<Hsla>(0xEC695E),
47 mac_os_traffic_light_yellow: rgb::<Hsla>(0xF4BF4F),
48 mac_os_traffic_light_green: rgb::<Hsla>(0x62C554),
49 }
50 }
51 pub fn color(&self) -> Hsla {
52 self.transparent
53 }
54}
55
56#[derive(Clone, Copy)]
57pub struct ThemeColor {
58 pub border: Hsla,
59 pub border_variant: Hsla,
60 pub border_focused: Hsla,
61 pub border_transparent: Hsla,
62 /// The background color of an elevated surface, like a modal, tooltip or toast.
63 pub elevated_surface: Hsla,
64 pub surface: Hsla,
65 /// Default background for elements like filled buttons,
66 /// text fields, checkboxes, radio buttons, etc.
67 /// - TODO: Map to step 3.
68 pub filled_element: Hsla,
69 /// The background color of a hovered element, like a button being hovered
70 /// with a mouse, or hovered on a touch screen.
71 /// - TODO: Map to step 4.
72 pub filled_element_hover: Hsla,
73 /// The background color of an active element, like a button being pressed,
74 /// or tapped on a touch screen.
75 /// - TODO: Map to step 5.
76 pub filled_element_active: Hsla,
77 /// The background color of a selected element, like a selected tab,
78 /// a button toggled on, or a checkbox that is checked.
79 pub filled_element_selected: Hsla,
80 pub filled_element_disabled: Hsla,
81 pub ghost_element: Hsla,
82 /// - TODO: Map to step 3.
83 pub ghost_element_hover: Hsla,
84 /// - TODO: Map to step 4.
85 pub ghost_element_active: Hsla,
86 pub ghost_element_selected: Hsla,
87 pub ghost_element_disabled: Hsla,
88}
89
90impl ThemeColor {
91 pub fn new(cx: &WindowContext) -> Self {
92 let theme = theme(cx);
93 let system_color = SystemColor::new();
94
95 Self {
96 border: theme.lowest.base.default.border,
97 border_variant: theme.lowest.variant.default.border,
98 border_focused: theme.lowest.accent.default.border,
99 border_transparent: system_color.transparent,
100 elevated_surface: theme.middle.base.default.background,
101 surface: theme.middle.base.default.background,
102 filled_element: theme.lowest.base.default.background,
103 filled_element_hover: theme.lowest.base.hovered.background,
104 filled_element_active: theme.lowest.base.active.background,
105 filled_element_selected: theme.lowest.accent.default.background,
106 filled_element_disabled: system_color.transparent,
107 ghost_element: system_color.transparent,
108 ghost_element_hover: theme.lowest.base.default.background,
109 ghost_element_active: theme.lowest.base.hovered.background,
110 ghost_element_selected: theme.lowest.accent.default.background,
111 ghost_element_disabled: system_color.transparent,
112 }
113 }
114}
115
116#[derive(Default, PartialEq, EnumIter, Clone, Copy)]
117pub enum HighlightColor {
118 #[default]
119 Default,
120 Comment,
121 String,
122 Function,
123 Keyword,
124}
125
126impl HighlightColor {
127 pub fn hsla(&self, theme: &Theme) -> Hsla {
128 let system_color = SystemColor::new();
129
130 match self {
131 Self::Default => theme
132 .syntax
133 .get("primary")
134 .cloned()
135 .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
136 Self::Comment => theme
137 .syntax
138 .get("comment")
139 .cloned()
140 .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
141 Self::String => theme
142 .syntax
143 .get("string")
144 .cloned()
145 .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
146 Self::Function => theme
147 .syntax
148 .get("function")
149 .cloned()
150 .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
151 Self::Keyword => theme
152 .syntax
153 .get("keyword")
154 .cloned()
155 .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
156 }
157 }
158}
159
160#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
161pub enum FileSystemStatus {
162 #[default]
163 None,
164 Conflict,
165 Deleted,
166}
167
168impl FileSystemStatus {
169 pub fn to_string(&self) -> String {
170 match self {
171 Self::None => "None".to_string(),
172 Self::Conflict => "Conflict".to_string(),
173 Self::Deleted => "Deleted".to_string(),
174 }
175 }
176}
177
178#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
179pub enum GitStatus {
180 #[default]
181 None,
182 Created,
183 Modified,
184 Deleted,
185 Conflict,
186 Renamed,
187}
188
189impl GitStatus {
190 pub fn to_string(&self) -> String {
191 match self {
192 Self::None => "None".to_string(),
193 Self::Created => "Created".to_string(),
194 Self::Modified => "Modified".to_string(),
195 Self::Deleted => "Deleted".to_string(),
196 Self::Conflict => "Conflict".to_string(),
197 Self::Renamed => "Renamed".to_string(),
198 }
199 }
200
201 pub fn hsla(&self, cx: &WindowContext) -> Hsla {
202 let theme = theme(cx);
203 let system_color = SystemColor::new();
204
205 match self {
206 Self::None => system_color.transparent,
207 Self::Created => theme.lowest.positive.default.foreground,
208 Self::Modified => theme.lowest.warning.default.foreground,
209 Self::Deleted => theme.lowest.negative.default.foreground,
210 Self::Conflict => theme.lowest.warning.default.foreground,
211 Self::Renamed => theme.lowest.accent.default.foreground,
212 }
213 }
214}
215
216#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
217pub enum DiagnosticStatus {
218 #[default]
219 None,
220 Error,
221 Warning,
222 Info,
223}
224
225#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
226pub enum IconSide {
227 #[default]
228 Left,
229 Right,
230}
231
232#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
233pub enum OrderMethod {
234 #[default]
235 Ascending,
236 Descending,
237 MostRecent,
238}
239
240#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
241pub enum Shape {
242 #[default]
243 Circle,
244 RoundedRectangle,
245}
246
247#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
248pub enum DisclosureControlVisibility {
249 #[default]
250 OnHover,
251 Always,
252}
253
254#[derive(Default, PartialEq, Copy, Clone, EnumIter, strum::Display)]
255pub enum InteractionState {
256 #[default]
257 Enabled,
258 Hovered,
259 Active,
260 Focused,
261 Disabled,
262}
263
264impl InteractionState {
265 pub fn if_enabled(&self, enabled: bool) -> Self {
266 if enabled {
267 *self
268 } else {
269 InteractionState::Disabled
270 }
271 }
272}
273
274#[derive(Default, PartialEq)]
275pub enum SelectedState {
276 #[default]
277 Unselected,
278 PartiallySelected,
279 Selected,
280}
281
282#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
283pub enum Toggleable {
284 Toggleable(ToggleState),
285 #[default]
286 NotToggleable,
287}
288
289impl Toggleable {
290 pub fn is_toggled(&self) -> bool {
291 match self {
292 Self::Toggleable(ToggleState::Toggled) => true,
293 _ => false,
294 }
295 }
296}
297
298impl From<ToggleState> for Toggleable {
299 fn from(state: ToggleState) -> Self {
300 Self::Toggleable(state)
301 }
302}
303
304#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
305pub enum ToggleState {
306 /// The "on" state of a toggleable element.
307 ///
308 /// Example:
309 /// - A collasable list that is currently expanded
310 /// - A toggle button that is currently on.
311 Toggled,
312 /// The "off" state of a toggleable element.
313 ///
314 /// Example:
315 /// - A collasable list that is currently collapsed
316 /// - A toggle button that is currently off.
317 #[default]
318 NotToggled,
319}
320
321impl From<Toggleable> for ToggleState {
322 fn from(toggleable: Toggleable) -> Self {
323 match toggleable {
324 Toggleable::Toggleable(state) => state,
325 Toggleable::NotToggleable => ToggleState::NotToggled,
326 }
327 }
328}
329
330impl From<bool> for ToggleState {
331 fn from(toggled: bool) -> Self {
332 if toggled {
333 ToggleState::Toggled
334 } else {
335 ToggleState::NotToggled
336 }
337 }
338}