prelude.rs

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