ZIm/crates/theme/src/scale.rs
Nathan Sobo 6fca1d2b0b
Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
2025-01-26 03:02:45 +00:00

298 lines
8.5 KiB
Rust

#![allow(missing_docs)]
use gpui::{App, Hsla, SharedString};
use crate::{ActiveTheme, Appearance};
/// A collection of colors that are used to style the UI.
///
/// Each step has a semantic meaning, and is used to style different parts of the UI.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct ColorScaleStep(usize);
impl ColorScaleStep {
pub const ONE: Self = Self(1);
pub const TWO: Self = Self(2);
pub const THREE: Self = Self(3);
pub const FOUR: Self = Self(4);
pub const FIVE: Self = Self(5);
pub const SIX: Self = Self(6);
pub const SEVEN: Self = Self(7);
pub const EIGHT: Self = Self(8);
pub const NINE: Self = Self(9);
pub const TEN: Self = Self(10);
pub const ELEVEN: Self = Self(11);
pub const TWELVE: Self = Self(12);
/// All of the steps in a [`ColorScale`].
pub const ALL: [ColorScaleStep; 12] = [
Self::ONE,
Self::TWO,
Self::THREE,
Self::FOUR,
Self::FIVE,
Self::SIX,
Self::SEVEN,
Self::EIGHT,
Self::NINE,
Self::TEN,
Self::ELEVEN,
Self::TWELVE,
];
}
/// A scale of colors for a given [`ColorScaleSet`].
///
/// Each [`ColorScale`] contains exactly 12 colors. Refer to
/// [`ColorScaleStep`] for a reference of what each step is used for.
pub struct ColorScale(Vec<Hsla>);
impl FromIterator<Hsla> for ColorScale {
fn from_iter<T: IntoIterator<Item = Hsla>>(iter: T) -> Self {
Self(Vec::from_iter(iter))
}
}
impl ColorScale {
/// Returns the specified step in the [`ColorScale`].
#[inline]
pub fn step(&self, step: ColorScaleStep) -> Hsla {
// Steps are one-based, so we need convert to the zero-based vec index.
self.0[step.0 - 1]
}
/// `Step 1` - Used for main application backgrounds.
///
/// This step provides a neutral base for any overlaying components, ideal for applications' main backdrop or empty spaces such as canvas areas.
///
#[inline]
pub fn step_1(&self) -> Hsla {
self.step(ColorScaleStep::ONE)
}
/// `Step 2` - Used for both main application backgrounds and subtle component backgrounds.
///
/// Like `Step 1`, this step allows variations in background styles, from striped tables, sidebar backgrounds, to card backgrounds.
#[inline]
pub fn step_2(&self) -> Hsla {
self.step(ColorScaleStep::TWO)
}
/// `Step 3` - Used for UI component backgrounds in their normal states.
///
/// This step maintains accessibility by guaranteeing a contrast ratio of 4.5:1 with steps 11 and 12 for text. It could also suit hover states for transparent components.
#[inline]
pub fn step_3(&self) -> Hsla {
self.step(ColorScaleStep::THREE)
}
/// `Step 4` - Used for UI component backgrounds in their hover states.
///
/// Also suited for pressed or selected states of components with a transparent background.
#[inline]
pub fn step_4(&self) -> Hsla {
self.step(ColorScaleStep::FOUR)
}
/// `Step 5` - Used for UI component backgrounds in their pressed or selected states.
#[inline]
pub fn step_5(&self) -> Hsla {
self.step(ColorScaleStep::FIVE)
}
/// `Step 6` - Used for subtle borders on non-interactive components.
///
/// Its usage spans from sidebars' borders, headers' dividers, cards' outlines, to alerts' edges and separators.
#[inline]
pub fn step_6(&self) -> Hsla {
self.step(ColorScaleStep::SIX)
}
/// `Step 7` - Used for subtle borders on interactive components.
///
/// This step subtly delineates the boundary of elements users interact with.
#[inline]
pub fn step_7(&self) -> Hsla {
self.step(ColorScaleStep::SEVEN)
}
/// `Step 8` - Used for stronger borders on interactive components and focus rings.
///
/// It strengthens the visibility and accessibility of active elements and their focus states.
#[inline]
pub fn step_8(&self) -> Hsla {
self.step(ColorScaleStep::EIGHT)
}
/// `Step 9` - Used for solid backgrounds.
///
/// `Step 9` is the most saturated step, having the least mix of white or black.
///
/// Due to its high chroma, `Step 9` is versatile and particularly useful for semantic colors such as
/// error, warning, and success indicators.
#[inline]
pub fn step_9(&self) -> Hsla {
self.step(ColorScaleStep::NINE)
}
/// `Step 10` - Used for hovered or active solid backgrounds, particularly when `Step 9` is their normal state.
///
/// May also be used for extremely low contrast text. This should be used sparingly, as it may be difficult to read.
#[inline]
pub fn step_10(&self) -> Hsla {
self.step(ColorScaleStep::TEN)
}
/// `Step 11` - Used for text and icons requiring low contrast or less emphasis.
#[inline]
pub fn step_11(&self) -> Hsla {
self.step(ColorScaleStep::ELEVEN)
}
/// `Step 12` - Used for text and icons requiring high contrast or prominence.
#[inline]
pub fn step_12(&self) -> Hsla {
self.step(ColorScaleStep::TWELVE)
}
}
pub struct ColorScales {
pub gray: ColorScaleSet,
pub mauve: ColorScaleSet,
pub slate: ColorScaleSet,
pub sage: ColorScaleSet,
pub olive: ColorScaleSet,
pub sand: ColorScaleSet,
pub gold: ColorScaleSet,
pub bronze: ColorScaleSet,
pub brown: ColorScaleSet,
pub yellow: ColorScaleSet,
pub amber: ColorScaleSet,
pub orange: ColorScaleSet,
pub tomato: ColorScaleSet,
pub red: ColorScaleSet,
pub ruby: ColorScaleSet,
pub crimson: ColorScaleSet,
pub pink: ColorScaleSet,
pub plum: ColorScaleSet,
pub purple: ColorScaleSet,
pub violet: ColorScaleSet,
pub iris: ColorScaleSet,
pub indigo: ColorScaleSet,
pub blue: ColorScaleSet,
pub cyan: ColorScaleSet,
pub teal: ColorScaleSet,
pub jade: ColorScaleSet,
pub green: ColorScaleSet,
pub grass: ColorScaleSet,
pub lime: ColorScaleSet,
pub mint: ColorScaleSet,
pub sky: ColorScaleSet,
pub black: ColorScaleSet,
pub white: ColorScaleSet,
}
impl IntoIterator for ColorScales {
type Item = ColorScaleSet;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
vec![
self.gray,
self.mauve,
self.slate,
self.sage,
self.olive,
self.sand,
self.gold,
self.bronze,
self.brown,
self.yellow,
self.amber,
self.orange,
self.tomato,
self.red,
self.ruby,
self.crimson,
self.pink,
self.plum,
self.purple,
self.violet,
self.iris,
self.indigo,
self.blue,
self.cyan,
self.teal,
self.jade,
self.green,
self.grass,
self.lime,
self.mint,
self.sky,
self.black,
self.white,
]
.into_iter()
}
}
/// Provides groups of [`ColorScale`]s for light and dark themes, as well as transparent versions of each scale.
pub struct ColorScaleSet {
name: SharedString,
light: ColorScale,
dark: ColorScale,
light_alpha: ColorScale,
dark_alpha: ColorScale,
}
impl ColorScaleSet {
pub fn new(
name: impl Into<SharedString>,
light: ColorScale,
light_alpha: ColorScale,
dark: ColorScale,
dark_alpha: ColorScale,
) -> Self {
Self {
name: name.into(),
light,
light_alpha,
dark,
dark_alpha,
}
}
pub fn name(&self) -> &SharedString {
&self.name
}
pub fn light(&self) -> &ColorScale {
&self.light
}
pub fn light_alpha(&self) -> &ColorScale {
&self.light_alpha
}
pub fn dark(&self) -> &ColorScale {
&self.dark
}
pub fn dark_alpha(&self) -> &ColorScale {
&self.dark_alpha
}
pub fn step(&self, cx: &App, step: ColorScaleStep) -> Hsla {
match cx.theme().appearance {
Appearance::Light => self.light().step(step),
Appearance::Dark => self.dark().step(step),
}
}
pub fn step_alpha(&self, cx: &App, step: ColorScaleStep) -> Hsla {
match cx.theme().appearance {
Appearance::Light => self.light_alpha.step(step),
Appearance::Dark => self.dark_alpha.step(step),
}
}
}