From a28799b65e4440fae72797006eaf30e4f45f38e5 Mon Sep 17 00:00:00 2001 From: Max Unsted Date: Mon, 2 May 2022 16:05:40 +0100 Subject: [PATCH] add pure version of color_palette example --- Cargo.toml | 1 + examples/pure/color_palette/Cargo.toml | 10 + examples/pure/color_palette/README.md | 15 + examples/pure/color_palette/screenshot.png | Bin 0 -> 44798 bytes examples/pure/color_palette/src/main.rs | 465 +++++++++++++++++++++ 5 files changed, 491 insertions(+) create mode 100644 examples/pure/color_palette/Cargo.toml create mode 100644 examples/pure/color_palette/README.md create mode 100644 examples/pure/color_palette/screenshot.png create mode 100644 examples/pure/color_palette/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 56b4d06a..2f6727eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,6 +91,7 @@ members = [ "examples/url_handler", "examples/websocket", "examples/pure/arc", + "examples/pure/color_palette", "examples/pure/component", "examples/pure/counter", "examples/pure/game_of_life", diff --git a/examples/pure/color_palette/Cargo.toml b/examples/pure/color_palette/Cargo.toml new file mode 100644 index 00000000..d08309d5 --- /dev/null +++ b/examples/pure/color_palette/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pure_color_palette" +version = "0.1.0" +authors = ["Clark Moody "] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../../..", features = ["pure", "canvas", "palette"] } +palette = "0.6.0" diff --git a/examples/pure/color_palette/README.md b/examples/pure/color_palette/README.md new file mode 100644 index 00000000..f90020b1 --- /dev/null +++ b/examples/pure/color_palette/README.md @@ -0,0 +1,15 @@ +## Color palette + +A color palette generator, based on a user-defined root color. + +
+ + + +
+ +You can run it with `cargo run`: + +``` +cargo run --package pure_color_palette +``` diff --git a/examples/pure/color_palette/screenshot.png b/examples/pure/color_palette/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e8da35c4d52705b9e6cfc34b9e98101b231b4233 GIT binary patch literal 44798 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 literal 0 HcmV?d00001 diff --git a/examples/pure/color_palette/src/main.rs b/examples/pure/color_palette/src/main.rs new file mode 100644 index 00000000..118c80cc --- /dev/null +++ b/examples/pure/color_palette/src/main.rs @@ -0,0 +1,465 @@ +use iced::pure::{ + column, row, text, + widget::canvas::{self, Canvas, Cursor, Frame, Geometry, Path}, + widget::Slider, + Element, Sandbox, +}; +use iced::{ + alignment, Alignment, Color, Length, Point, Rectangle, Settings, Size, + Vector, +}; +use palette::{self, convert::FromColor, Hsl, Srgb}; +use std::marker::PhantomData; +use std::ops::RangeInclusive; + +pub fn main() -> iced::Result { + ColorPalette::run(Settings { + antialiasing: true, + ..Settings::default() + }) +} + +#[derive(Default)] +pub struct ColorPalette { + theme: Theme, + rgb: ColorPicker, + hsl: ColorPicker, + hsv: ColorPicker, + hwb: ColorPicker, + lab: ColorPicker, + lch: ColorPicker, +} + +#[derive(Debug, Clone, Copy)] +pub enum Message { + RgbColorChanged(Color), + HslColorChanged(palette::Hsl), + HsvColorChanged(palette::Hsv), + HwbColorChanged(palette::Hwb), + LabColorChanged(palette::Lab), + LchColorChanged(palette::Lch), +} + +impl Sandbox for ColorPalette { + type Message = Message; + + fn new() -> Self { + Self::default() + } + + fn title(&self) -> String { + String::from("Color palette - Iced") + } + + fn update(&mut self, message: Message) { + let srgb = match message { + Message::RgbColorChanged(rgb) => palette::Srgb::from(rgb), + Message::HslColorChanged(hsl) => palette::Srgb::from_color(hsl), + Message::HsvColorChanged(hsv) => palette::Srgb::from_color(hsv), + Message::HwbColorChanged(hwb) => palette::Srgb::from_color(hwb), + Message::LabColorChanged(lab) => palette::Srgb::from_color(lab), + Message::LchColorChanged(lch) => palette::Srgb::from_color(lch), + }; + + self.theme = Theme::new(srgb); + } + + fn view(&self) -> Element { + let base = self.theme.base; + + let srgb = palette::Srgb::from(base); + let hsl = palette::Hsl::from_color(srgb); + let hsv = palette::Hsv::from_color(srgb); + let hwb = palette::Hwb::from_color(srgb); + let lab = palette::Lab::from_color(srgb); + let lch = palette::Lch::from_color(srgb); + + column() + .padding(10) + .spacing(10) + .push(self.rgb.view(base).map(Message::RgbColorChanged)) + .push(self.hsl.view(hsl).map(Message::HslColorChanged)) + .push(self.hsv.view(hsv).map(Message::HsvColorChanged)) + .push(self.hwb.view(hwb).map(Message::HwbColorChanged)) + .push(self.lab.view(lab).map(Message::LabColorChanged)) + .push(self.lch.view(lch).map(Message::LchColorChanged)) + .push(self.theme.view()) + .into() + } +} + +#[derive(Debug)] +pub struct Theme { + lower: Vec, + base: Color, + higher: Vec, + canvas_cache: canvas::Cache, +} + +impl Theme { + pub fn new(base: impl Into) -> Theme { + use palette::{Hue, Shade}; + + let base = base.into(); + + // Convert to HSL color for manipulation + let hsl = Hsl::from_color(Srgb::from(base)); + + let lower = [ + hsl.shift_hue(-135.0).lighten(0.075), + hsl.shift_hue(-120.0), + hsl.shift_hue(-105.0).darken(0.075), + hsl.darken(0.075), + ]; + + let higher = [ + hsl.lighten(0.075), + hsl.shift_hue(105.0).darken(0.075), + hsl.shift_hue(120.0), + hsl.shift_hue(135.0).lighten(0.075), + ]; + + Theme { + lower: lower + .iter() + .map(|&color| Srgb::from_color(color).into()) + .collect(), + base, + higher: higher + .iter() + .map(|&color| Srgb::from_color(color).into()) + .collect(), + canvas_cache: canvas::Cache::default(), + } + } + + pub fn len(&self) -> usize { + self.lower.len() + self.higher.len() + 1 + } + + pub fn colors(&self) -> impl Iterator { + self.lower + .iter() + .chain(std::iter::once(&self.base)) + .chain(self.higher.iter()) + } + + pub fn view(&self) -> Element { + Canvas::new(self) + .width(Length::Fill) + .height(Length::Fill) + .into() + } + + fn draw(&self, frame: &mut Frame) { + let pad = 20.0; + + let box_size = Size { + width: frame.width() / self.len() as f32, + height: frame.height() / 2.0 - pad, + }; + + let triangle = Path::new(|path| { + path.move_to(Point { x: 0.0, y: -0.5 }); + path.line_to(Point { x: -0.5, y: 0.0 }); + path.line_to(Point { x: 0.5, y: 0.0 }); + path.close(); + }); + + let mut text = canvas::Text { + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Top, + size: 15.0, + ..canvas::Text::default() + }; + + for (i, &color) in self.colors().enumerate() { + let anchor = Point { + x: (i as f32) * box_size.width, + y: 0.0, + }; + frame.fill_rectangle(anchor, box_size, color); + + // We show a little indicator for the base color + if color == self.base { + let triangle_x = anchor.x + box_size.width / 2.0; + + frame.with_save(|frame| { + frame.translate(Vector::new(triangle_x, 0.0)); + frame.scale(10.0); + frame.rotate(std::f32::consts::PI); + + frame.fill(&triangle, Color::WHITE); + }); + + frame.with_save(|frame| { + frame.translate(Vector::new(triangle_x, box_size.height)); + frame.scale(10.0); + + frame.fill(&triangle, Color::WHITE); + }); + } + + frame.fill_text(canvas::Text { + content: color_hex_string(&color), + position: Point { + x: anchor.x + box_size.width / 2.0, + y: box_size.height, + }, + ..text + }); + } + + text.vertical_alignment = alignment::Vertical::Bottom; + + let hsl = Hsl::from_color(Srgb::from(self.base)); + for i in 0..self.len() { + let pct = (i as f32 + 1.0) / (self.len() as f32 + 1.0); + let graded = Hsl { + lightness: 1.0 - pct, + ..hsl + }; + let color: Color = Srgb::from_color(graded).into(); + + let anchor = Point { + x: (i as f32) * box_size.width, + y: box_size.height + 2.0 * pad, + }; + + frame.fill_rectangle(anchor, box_size, color); + + frame.fill_text(canvas::Text { + content: color_hex_string(&color), + position: Point { + x: anchor.x + box_size.width / 2.0, + y: box_size.height + 2.0 * pad, + }, + ..text + }); + } + } +} + +impl canvas::Program for Theme { + type State = (); + + fn draw( + &self, + _state: &Self::State, + _theme: &iced::Theme, + bounds: Rectangle, + _cursor: Cursor, + ) -> Vec { + let theme = self.canvas_cache.draw(bounds.size(), |frame| { + self.draw(frame); + }); + + vec![theme] + } +} + +impl Default for Theme { + fn default() -> Self { + Theme::new(Color::from_rgb8(75, 128, 190)) + } +} + +fn color_hex_string(color: &Color) -> String { + format!( + "#{:x}{:x}{:x}", + (255.0 * color.r).round() as u8, + (255.0 * color.g).round() as u8, + (255.0 * color.b).round() as u8 + ) +} + +#[derive(Default)] +struct ColorPicker { + color_space: PhantomData, +} + +trait ColorSpace: Sized { + const LABEL: &'static str; + const COMPONENT_RANGES: [RangeInclusive; 3]; + + fn new(a: f32, b: f32, c: f32) -> Self; + + fn components(&self) -> [f32; 3]; + + fn to_string(&self) -> String; +} + +impl ColorPicker { + fn view(&self, color: C) -> Element { + let [c1, c2, c3] = color.components(); + let [cr1, cr2, cr3] = C::COMPONENT_RANGES; + + fn slider<'a, C: Clone>( + range: RangeInclusive, + component: f32, + update: impl Fn(f32) -> C + 'a, + ) -> Slider<'a, f64, C, iced::Renderer> { + Slider::new(range, f64::from(component), move |v| update(v as f32)) + .step(0.01) + } + + row() + .spacing(10) + .align_items(Alignment::Center) + .push(text(C::LABEL).width(Length::Units(50))) + .push(slider(cr1, c1, move |v| C::new(v, c2, c3))) + .push(slider(cr2, c2, move |v| C::new(c1, v, c3))) + .push(slider(cr3, c3, move |v| C::new(c1, c2, v))) + .push(text(color.to_string()).width(Length::Units(185)).size(14)) + .into() + } +} + +impl ColorSpace for Color { + const LABEL: &'static str = "RGB"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=1.0, 0.0..=1.0, 0.0..=1.0]; + + fn new(r: f32, g: f32, b: f32) -> Self { + Color::from_rgb(r, g, b) + } + + fn components(&self) -> [f32; 3] { + [self.r, self.g, self.b] + } + + fn to_string(&self) -> String { + format!( + "rgb({:.0}, {:.0}, {:.0})", + 255.0 * self.r, + 255.0 * self.g, + 255.0 * self.b + ) + } +} + +impl ColorSpace for palette::Hsl { + const LABEL: &'static str = "HSL"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=360.0, 0.0..=1.0, 0.0..=1.0]; + + fn new(hue: f32, saturation: f32, lightness: f32) -> Self { + palette::Hsl::new( + palette::RgbHue::from_degrees(hue), + saturation, + lightness, + ) + } + + fn components(&self) -> [f32; 3] { + [ + self.hue.to_positive_degrees(), + self.saturation, + self.lightness, + ] + } + + fn to_string(&self) -> String { + format!( + "hsl({:.1}, {:.1}%, {:.1}%)", + self.hue.to_positive_degrees(), + 100.0 * self.saturation, + 100.0 * self.lightness + ) + } +} + +impl ColorSpace for palette::Hsv { + const LABEL: &'static str = "HSV"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=360.0, 0.0..=1.0, 0.0..=1.0]; + + fn new(hue: f32, saturation: f32, value: f32) -> Self { + palette::Hsv::new(palette::RgbHue::from_degrees(hue), saturation, value) + } + + fn components(&self) -> [f32; 3] { + [self.hue.to_positive_degrees(), self.saturation, self.value] + } + + fn to_string(&self) -> String { + format!( + "hsv({:.1}, {:.1}%, {:.1}%)", + self.hue.to_positive_degrees(), + 100.0 * self.saturation, + 100.0 * self.value + ) + } +} + +impl ColorSpace for palette::Hwb { + const LABEL: &'static str = "HWB"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=360.0, 0.0..=1.0, 0.0..=1.0]; + + fn new(hue: f32, whiteness: f32, blackness: f32) -> Self { + palette::Hwb::new( + palette::RgbHue::from_degrees(hue), + whiteness, + blackness, + ) + } + + fn components(&self) -> [f32; 3] { + [ + self.hue.to_positive_degrees(), + self.whiteness, + self.blackness, + ] + } + + fn to_string(&self) -> String { + format!( + "hwb({:.1}, {:.1}%, {:.1}%)", + self.hue.to_positive_degrees(), + 100.0 * self.whiteness, + 100.0 * self.blackness + ) + } +} + +impl ColorSpace for palette::Lab { + const LABEL: &'static str = "Lab"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=100.0, -128.0..=127.0, -128.0..=127.0]; + + fn new(l: f32, a: f32, b: f32) -> Self { + palette::Lab::new(l, a, b) + } + + fn components(&self) -> [f32; 3] { + [self.l, self.a, self.b] + } + + fn to_string(&self) -> String { + format!("Lab({:.1}, {:.1}, {:.1})", self.l, self.a, self.b) + } +} + +impl ColorSpace for palette::Lch { + const LABEL: &'static str = "Lch"; + const COMPONENT_RANGES: [RangeInclusive; 3] = + [0.0..=100.0, 0.0..=128.0, 0.0..=360.0]; + + fn new(l: f32, chroma: f32, hue: f32) -> Self { + palette::Lch::new(l, chroma, palette::LabHue::from_degrees(hue)) + } + + fn components(&self) -> [f32; 3] { + [self.l, self.chroma, self.hue.to_positive_degrees()] + } + + fn to_string(&self) -> String { + format!( + "Lch({:.1}, {:.1}, {:.1})", + self.l, + self.chroma, + self.hue.to_positive_degrees() + ) + } +}