prelude.rs

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