Update docs
This commit is contained in:
parent
dde0056845
commit
4cdcac1b16
1 changed files with 57 additions and 36 deletions
|
@ -4,25 +4,49 @@
|
||||||
//!
|
//!
|
||||||
//! It is used to create a manipulate colors when building themes.
|
//! It is used to create a manipulate colors when building themes.
|
||||||
//!
|
//!
|
||||||
//! **Note:** This crate does not depend on `gpui`, so it does not provide any
|
//! === In development note ===
|
||||||
//! interfaces for converting to `gpui` style colors.
|
//!
|
||||||
|
//! This crate is meant to sit between gpui and the theme/ui for all the color related stuff.
|
||||||
|
//!
|
||||||
|
//! It could be folded into gpui, ui or theme potentially but for now we'll continue
|
||||||
|
//! to develop it in isolation.
|
||||||
|
//!
|
||||||
|
//! Once we have a good idea of the needs of the theme system and color in gpui in general I see 3 paths:
|
||||||
|
//! 1. Use `palette` (or another color library) directly in gpui and everywhere else, rather than rolling our own color system.
|
||||||
|
//! 2. Keep this crate as a thin wrapper around `palette` and use it everywhere except gpui, and convert to gpui's color system when needed.
|
||||||
|
//! 3. Build the needed functionality into gpui and keep using it's color system everywhere.
|
||||||
|
//!
|
||||||
|
//! I'm leaning towards 2 in the short term and 1 in the long term, but we'll need to discuss it more.
|
||||||
|
//!
|
||||||
|
//! === End development note ===
|
||||||
use palette::{
|
use palette::{
|
||||||
blend::Blend, convert::FromColorUnclamped, encoding, rgb::Rgb, Clamp, Mix, Srgb, WithAlpha,
|
blend::Blend, convert::FromColorUnclamped, encoding, rgb::Rgb, Clamp, Mix, Srgb, WithAlpha,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The types of blend modes supported
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum BlendMode {
|
pub enum BlendMode {
|
||||||
|
/// Multiplies the colors, resulting in a darker color. This mode is useful for creating shadows.
|
||||||
Multiply,
|
Multiply,
|
||||||
|
/// Lightens the color by adding the source and destination colors. It results in a lighter color.
|
||||||
Screen,
|
Screen,
|
||||||
|
/// Combines Multiply and Screen blend modes. Parts of the image that are lighter than 50% gray are lightened, and parts that are darker are darkened.
|
||||||
Overlay,
|
Overlay,
|
||||||
|
/// Selects the darker of the base or blend color as the resulting color. Useful for darkening images without affecting the overall contrast.
|
||||||
Darken,
|
Darken,
|
||||||
|
/// Selects the lighter of the base or blend color as the resulting color. Useful for lightening images without affecting the overall contrast.
|
||||||
Lighten,
|
Lighten,
|
||||||
|
/// Brightens the base color to reflect the blend color. The result is a lightened image.
|
||||||
Dodge,
|
Dodge,
|
||||||
|
/// Darkens the base color to reflect the blend color. The result is a darkened image.
|
||||||
Burn,
|
Burn,
|
||||||
|
/// Similar to Overlay, but with a stronger effect. Hard Light can either multiply or screen colors, depending on the blend color.
|
||||||
HardLight,
|
HardLight,
|
||||||
|
/// A softer version of Hard Light. Soft Light either darkens or lightens colors, depending on the blend color.
|
||||||
SoftLight,
|
SoftLight,
|
||||||
|
/// Subtracts the darker of the two constituent colors from the lighter color. Difference mode is useful for creating more vivid colors.
|
||||||
Difference,
|
Difference,
|
||||||
|
/// Similar to Difference, but with a lower contrast. Exclusion mode produces an effect similar to Difference but with less intensity.
|
||||||
Exclusion,
|
Exclusion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +54,7 @@ pub enum BlendMode {
|
||||||
///
|
///
|
||||||
/// This function supports the following hex formats:
|
/// This function supports the following hex formats:
|
||||||
/// `#RGB`, `#RGBA`, `#RRGGBB`, `#RRGGBBAA`.
|
/// `#RGB`, `#RGBA`, `#RRGGBB`, `#RRGGBBAA`.
|
||||||
pub fn hex_to_hsla(s: &str) -> Result<Color, String> {
|
pub fn hex_to_hsla(s: &str) -> Result<RGBAColor, String> {
|
||||||
let hex = s.trim_start_matches('#');
|
let hex = s.trim_start_matches('#');
|
||||||
|
|
||||||
// Expand shorthand formats #RGB and #RGBA to #RRGGBB and #RRGGBBAA
|
// Expand shorthand formats #RGB and #RGBA to #RRGGBB and #RRGGBBAA
|
||||||
|
@ -61,16 +85,15 @@ pub fn hex_to_hsla(s: &str) -> Result<Color, String> {
|
||||||
let b = ((hex_val >> 8) & 0xFF) as f32 / 255.0;
|
let b = ((hex_val >> 8) & 0xFF) as f32 / 255.0;
|
||||||
let a = (hex_val & 0xFF) as f32 / 255.0;
|
let a = (hex_val & 0xFF) as f32 / 255.0;
|
||||||
|
|
||||||
let color = Color { r, g, b, a };
|
let color = RGBAColor { r, g, b, a };
|
||||||
|
|
||||||
Ok(color)
|
Ok(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This implements conversion to and from all Palette colors.
|
// These derives implement to and from palette's color types.
|
||||||
#[derive(FromColorUnclamped, WithAlpha, Debug, Clone)]
|
#[derive(FromColorUnclamped, WithAlpha, Debug, Clone)]
|
||||||
// We have to tell Palette that we will take care of converting to/from sRGB.
|
|
||||||
#[palette(skip_derives(Rgb), rgb_standard = "encoding::Srgb")]
|
#[palette(skip_derives(Rgb), rgb_standard = "encoding::Srgb")]
|
||||||
pub struct Color {
|
pub struct RGBAColor {
|
||||||
r: f32,
|
r: f32,
|
||||||
g: f32,
|
g: f32,
|
||||||
b: f32,
|
b: f32,
|
||||||
|
@ -79,22 +102,19 @@ pub struct Color {
|
||||||
a: f32,
|
a: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// There's no blanket implementation for Self -> Self, unlike the From trait.
|
impl FromColorUnclamped<RGBAColor> for RGBAColor {
|
||||||
// This is to better allow cases like Self<A> -> Self<B>.
|
fn from_color_unclamped(color: RGBAColor) -> RGBAColor {
|
||||||
impl FromColorUnclamped<Color> for Color {
|
|
||||||
fn from_color_unclamped(color: Color) -> Color {
|
|
||||||
color
|
color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert from any kind of f32 sRGB.
|
impl<S> FromColorUnclamped<Rgb<S, f32>> for RGBAColor
|
||||||
impl<S> FromColorUnclamped<Rgb<S, f32>> for Color
|
|
||||||
where
|
where
|
||||||
Srgb: FromColorUnclamped<Rgb<S, f32>>,
|
Srgb: FromColorUnclamped<Rgb<S, f32>>,
|
||||||
{
|
{
|
||||||
fn from_color_unclamped(color: Rgb<S, f32>) -> Color {
|
fn from_color_unclamped(color: Rgb<S, f32>) -> RGBAColor {
|
||||||
let srgb = Srgb::from_color_unclamped(color);
|
let srgb = Srgb::from_color_unclamped(color);
|
||||||
Color {
|
RGBAColor {
|
||||||
r: srgb.red,
|
r: srgb.red,
|
||||||
g: srgb.green,
|
g: srgb.green,
|
||||||
b: srgb.blue,
|
b: srgb.blue,
|
||||||
|
@ -103,21 +123,19 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert into any kind of f32 sRGB.
|
impl<S> FromColorUnclamped<RGBAColor> for Rgb<S, f32>
|
||||||
impl<S> FromColorUnclamped<Color> for Rgb<S, f32>
|
|
||||||
where
|
where
|
||||||
Rgb<S, f32>: FromColorUnclamped<Srgb>,
|
Rgb<S, f32>: FromColorUnclamped<Srgb>,
|
||||||
{
|
{
|
||||||
fn from_color_unclamped(color: Color) -> Self {
|
fn from_color_unclamped(color: RGBAColor) -> Self {
|
||||||
let srgb = Srgb::new(color.r, color.g, color.b);
|
let srgb = Srgb::new(color.r, color.g, color.b);
|
||||||
Self::from_color_unclamped(srgb)
|
Self::from_color_unclamped(srgb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the required clamping.
|
impl Clamp for RGBAColor {
|
||||||
impl Clamp for Color {
|
|
||||||
fn clamp(self) -> Self {
|
fn clamp(self) -> Self {
|
||||||
Color {
|
RGBAColor {
|
||||||
r: self.r.min(1.0).max(0.0),
|
r: self.r.min(1.0).max(0.0),
|
||||||
g: self.g.min(1.0).max(0.0),
|
g: self.g.min(1.0).max(0.0),
|
||||||
b: self.b.min(1.0).max(0.0),
|
b: self.b.min(1.0).max(0.0),
|
||||||
|
@ -126,9 +144,12 @@ impl Clamp for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color {
|
impl RGBAColor {
|
||||||
|
/// Creates a new color from the given RGBA values.
|
||||||
|
///
|
||||||
|
/// This color can be used to convert to any [`palette::Color`] type.
|
||||||
pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||||
Color { r, g, b, a }
|
RGBAColor { r, g, b, a }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a set of states for this color.
|
/// Returns a set of states for this color.
|
||||||
|
@ -137,16 +158,16 @@ impl Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mixes this color with another [`palette::Hsl`] color at the given `mix_ratio`.
|
/// Mixes this color with another [`palette::Hsl`] color at the given `mix_ratio`.
|
||||||
pub fn mixed(&self, other: Color, mix_ratio: f32) -> Self {
|
pub fn mixed(&self, other: RGBAColor, mix_ratio: f32) -> Self {
|
||||||
let srgb_self = Srgb::new(self.r, self.g, self.b);
|
let srgb_self = Srgb::new(self.r, self.g, self.b);
|
||||||
let srgb_other = Srgb::new(other.r, other.g, other.b);
|
let srgb_other = Srgb::new(other.r, other.g, other.b);
|
||||||
|
|
||||||
// Directly mix the colors as sRGB values
|
// Directly mix the colors as sRGB values
|
||||||
let mixed = srgb_self.mix(srgb_other, mix_ratio);
|
let mixed = srgb_self.mix(srgb_other, mix_ratio);
|
||||||
Color::from_color_unclamped(mixed)
|
RGBAColor::from_color_unclamped(mixed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blend(&self, other: Color, blend_mode: BlendMode) -> Self {
|
pub fn blend(&self, other: RGBAColor, blend_mode: BlendMode) -> Self {
|
||||||
let srgb_self = Srgb::new(self.r, self.g, self.b);
|
let srgb_self = Srgb::new(self.r, self.g, self.b);
|
||||||
let srgb_other = Srgb::new(other.r, other.g, other.b);
|
let srgb_other = Srgb::new(other.r, other.g, other.b);
|
||||||
|
|
||||||
|
@ -169,31 +190,31 @@ impl Color {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ColorStates {
|
pub struct ColorStates {
|
||||||
/// The default color.
|
/// The default color.
|
||||||
pub default: Color,
|
pub default: RGBAColor,
|
||||||
/// The color when the mouse is hovering over the element.
|
/// The color when the mouse is hovering over the element.
|
||||||
pub hover: Color,
|
pub hover: RGBAColor,
|
||||||
/// The color when the mouse button is held down on the element.
|
/// The color when the mouse button is held down on the element.
|
||||||
pub active: Color,
|
pub active: RGBAColor,
|
||||||
/// The color when the element is focused with the keyboard.
|
/// The color when the element is focused with the keyboard.
|
||||||
pub focused: Color,
|
pub focused: RGBAColor,
|
||||||
/// The color when the element is disabled.
|
/// The color when the element is disabled.
|
||||||
pub disabled: Color,
|
pub disabled: RGBAColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a set of colors for different states of an element.
|
/// Returns a set of colors for different states of an element.
|
||||||
///
|
///
|
||||||
/// todo!("Test and improve this function")
|
/// todo!("This should take a theme and use appropriate colors from it")
|
||||||
pub fn states_for_color(color: Color, is_light: bool) -> ColorStates {
|
pub fn states_for_color(color: RGBAColor, is_light: bool) -> ColorStates {
|
||||||
let adjustment_factor = if is_light { 0.1 } else { -0.1 };
|
let adjustment_factor = if is_light { 0.1 } else { -0.1 };
|
||||||
let hover_adjustment = 1.0 - adjustment_factor;
|
let hover_adjustment = 1.0 - adjustment_factor;
|
||||||
let active_adjustment = 1.0 - 2.0 * adjustment_factor;
|
let active_adjustment = 1.0 - 2.0 * adjustment_factor;
|
||||||
let focused_adjustment = 1.0 - 3.0 * adjustment_factor;
|
let focused_adjustment = 1.0 - 3.0 * adjustment_factor;
|
||||||
let disabled_adjustment = 1.0 - 4.0 * adjustment_factor;
|
let disabled_adjustment = 1.0 - 4.0 * adjustment_factor;
|
||||||
|
|
||||||
let make_adjustment = |color: Color, adjustment: f32| -> Color {
|
let make_adjustment = |color: RGBAColor, adjustment: f32| -> RGBAColor {
|
||||||
// Adjust lightness for each state
|
// Adjust lightness for each state
|
||||||
// Note: Adjustment logic may differ; simplify as needed for sRGB
|
// Note: Adjustment logic may differ; simplify as needed for sRGB
|
||||||
Color::new(
|
RGBAColor::new(
|
||||||
color.r * adjustment,
|
color.r * adjustment,
|
||||||
color.g * adjustment,
|
color.g * adjustment,
|
||||||
color.b * adjustment,
|
color.b * adjustment,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue