From 0c02266aa7b3a31fdf34bc60f661244fc19414b5 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Thu, 12 Oct 2023 12:45:57 -0400 Subject: [PATCH] wip: add plus icon to empty color picker button --- examples/cosmic/src/window/demo.rs | 9 +- src/widget/color_picker/mod.rs | 212 ++++++++++++++++------------- 2 files changed, 124 insertions(+), 97 deletions(-) diff --git a/examples/cosmic/src/window/demo.rs b/examples/cosmic/src/window/demo.rs index c0dcecb2..101b16af 100644 --- a/examples/cosmic/src/window/demo.rs +++ b/examples/cosmic/src/window/demo.rs @@ -160,12 +160,7 @@ impl Default for State { "card 4".to_string(), ], timeline: Rc::new(RefCell::new(Default::default())), - color_picker_model: ColorPickerModel::new( - "Hex", - "RGB", - Some(Color::new(0.8, 0.3, 0.8, 1.0)), - None, - ), + color_picker_model: ColorPickerModel::new("Hex", "RGB", None, None), } } } @@ -525,6 +520,8 @@ impl State { .into(), self.color_picker_model .picker_button(Message::ColorPickerUpdate) + .width(Length::Fixed(128.0)) + .height(Length::Fixed(128.0)) .into(), if self.color_picker_model.get_is_active() { self.color_picker_model diff --git a/src/widget/color_picker/mod.rs b/src/widget/color_picker/mod.rs index 012d3e9d..cf700332 100644 --- a/src/widget/color_picker/mod.rs +++ b/src/widget/color_picker/mod.rs @@ -17,20 +17,21 @@ use iced_core::gradient::{ColorStop, Linear}; use iced_core::renderer::Quad; use iced_core::widget::{tree, Tree}; use iced_core::{ - layout, mouse, renderer, Clipboard, Color, Layout, Length, Radians, Rectangle, Renderer, Shell, - Vector, Widget, + layout, mouse, renderer, Background, Clipboard, Color, Layout, Length, Radians, Rectangle, + Renderer, Shell, Vector, Widget, }; #[cfg(feature = "wayland")] use iced_sctk::commands::data_device::set_selection; use iced_style::slider::{HandleShape, RailBackground}; -use iced_widget::{canvas, column, scrollable, vertical_space, Row}; +use iced_widget::{canvas, column, horizontal_space, row, scrollable, vertical_space, Row}; use lazy_static::lazy_static; use palette::{FromColor, RgbHue}; +use super::button::StyleSheet; use super::divider::horizontal; -use super::icon::from_name; +use super::icon::{self, from_name}; use super::segmented_button::{self, Model, SingleSelect}; -use super::{button, segmented_selection, text, text_input, tooltip}; +use super::{button, segmented_selection, text, text_input, tooltip, Icon}; // TODO is this going to look correct enough? lazy_static! { @@ -74,8 +75,6 @@ pub struct ColorPickerModel { #[setters(skip)] applied_color: Option, #[setters(skip)] - initial_color: Option, - #[setters(skip)] fallback_color: Option, #[setters(skip)] recent_colors: Vec, @@ -108,7 +107,6 @@ impl ColorPickerModel { save_next: None, input_color: color_to_string(hsv, true), applied_color: initial, - initial_color, fallback_color, recent_colors: Vec::new(), // TODO should all color pickers show the same recent colors? active: false, @@ -121,13 +119,13 @@ impl ColorPickerModel { /// Get a color picker button that displays the applied color /// - pub fn picker_button<'a, Message: 'a, T: Fn(ColorPickerUpdate) -> Message>( + pub fn picker_button<'a, Message: 'static, T: Fn(ColorPickerUpdate) -> Message>( &self, f: T, ) -> crate::widget::Button<'a, Message, crate::Renderer> { color_button( Some(f(ColorPickerUpdate::ToggleColorPicker)), - self.applied_color.unwrap_or(Color::BLACK), + self.applied_color, ) } @@ -360,7 +358,7 @@ where .leading_icon( color_button( None, - Color::from(palette::Srgb::from_color(self.active_color)) + Some(Color::from(palette::Srgb::from_color(self.active_color))) ) .into() ) @@ -416,7 +414,7 @@ where let hsv = palette::Hsv::from_color(initial_srgb); color_button( Some(on_update(ColorPickerUpdate::ActiveColor(hsv))), - *c, + Some(*c), ) .into() }) @@ -743,93 +741,125 @@ fn color_to_string(c: palette::Hsv, is_hex: bool) -> String { } } -fn color_button<'a, Message: 'a>( +fn color_button<'a, Message: 'static>( on_press: Option, - color: Color, + color: Option, ) -> crate::widget::Button<'a, Message, crate::Renderer> { let spacing = THEME.with(|t| t.borrow().cosmic().spacing); - button(vertical_space(Length::Fixed(f32::from(spacing.space_s)))) - .width(Length::Fixed(f32::from(spacing.space_s))) - .height(Length::Fixed(f32::from(spacing.space_s))) - .on_press_maybe(on_press) - .style(crate::theme::Button::Custom { - active: Box::new(move |focused, theme| { - let cosmic = theme.cosmic(); + button(if color.is_some() { + Element::from(vertical_space(Length::Fixed(f32::from(spacing.space_s)))) + } else { + Element::from(column![ + vertical_space(Length::FillPortion(1)), + vertical_space(Length::FillPortion(1)), + row![ + horizontal_space(Length::FillPortion(1)), + horizontal_space(Length::FillPortion(1)), + Icon::from( + icon::from_name("list-add-symbolic") + .prefer_svg(true) + .symbolic(true) + .size(64) + ) + .width(Length::FillPortion(2)) + .height(Length::Fill) + .content_fit(iced_core::ContentFit::Contain), + horizontal_space(Length::FillPortion(1)), + horizontal_space(Length::FillPortion(1)), + ] + .height(Length::FillPortion(2)) + .width(Length::Fill), + vertical_space(Length::FillPortion(1)), + vertical_space(Length::FillPortion(1)), + ]) + }) + .width(Length::Fixed(f32::from(spacing.space_s))) + .height(Length::Fixed(f32::from(spacing.space_s))) + .on_press_maybe(on_press) + .style(crate::theme::Button::Custom { + active: Box::new(move |focused, theme| { + let cosmic = theme.cosmic(); - let (outline_width, outline_color) = if focused { - (1.0, cosmic.accent_color().into()) - } else { - (0.0, Color::TRANSPARENT) - }; - button::Appearance { - shadow_offset: Vector::default(), - background: Some(color.into()), - border_radius: cosmic.radius_xs().into(), - border_width: 1.0, - border_color: cosmic.on_bg_color().into(), - outline_width, - outline_color, - icon_color: None, - text_color: None, - } - }), - disabled: Box::new(move |theme| { - let cosmic = theme.cosmic(); + let (outline_width, outline_color) = if focused { + (1.0, cosmic.accent_color().into()) + } else { + (0.0, Color::TRANSPARENT) + }; + let standard = theme.active(focused, &Button::Standard); + button::Appearance { + shadow_offset: Vector::default(), + background: color.map(Background::from).or(standard.background), + border_radius: cosmic.radius_xs().into(), + border_width: 1.0, + border_color: cosmic.on_bg_color().into(), + outline_width, + outline_color, + icon_color: None, + text_color: None, + } + }), + disabled: Box::new(move |theme| { + let cosmic = theme.cosmic(); - button::Appearance { - shadow_offset: Vector::default(), - background: Some(color.into()), - border_radius: cosmic.radius_xs().into(), - border_width: 1.0, - border_color: cosmic.on_bg_color().into(), - outline_width: 0.0, - outline_color: Color::TRANSPARENT, - icon_color: None, - text_color: None, - } - }), - hovered: Box::new(move |focused, theme| { - let cosmic = theme.cosmic(); + let standard = theme.disabled(&Button::Standard); + button::Appearance { + shadow_offset: Vector::default(), + background: color.map(Background::from).or(standard.background), + border_radius: cosmic.radius_xs().into(), + border_width: 1.0, + border_color: cosmic.on_bg_color().into(), + outline_width: 0.0, + outline_color: Color::TRANSPARENT, + icon_color: None, + text_color: None, + } + }), + hovered: Box::new(move |focused, theme| { + let cosmic = theme.cosmic(); - let (outline_width, outline_color) = if focused { - (1.0, cosmic.accent_color().into()) - } else { - (0.0, Color::TRANSPARENT) - }; - button::Appearance { - shadow_offset: Vector::default(), - background: Some(color.into()), - border_radius: cosmic.radius_xs().into(), - border_width: 1.0, - border_color: cosmic.on_bg_color().into(), - outline_width, - outline_color, - icon_color: None, - text_color: None, - } - }), - pressed: Box::new(move |focused, theme| { - let cosmic = theme.cosmic(); + let (outline_width, outline_color) = if focused { + (1.0, cosmic.accent_color().into()) + } else { + (0.0, Color::TRANSPARENT) + }; - let (outline_width, outline_color) = if focused { - (1.0, cosmic.accent_color().into()) - } else { - (0.0, Color::TRANSPARENT) - }; - button::Appearance { - shadow_offset: Vector::default(), - background: Some(color.into()), - border_radius: cosmic.radius_xs().into(), - border_width: 1.0, - border_color: cosmic.on_bg_color().into(), - outline_width, - outline_color, - icon_color: None, - text_color: None, - } - }), - }) + let standard = theme.hovered(focused, &Button::Standard); + button::Appearance { + shadow_offset: Vector::default(), + background: color.map(Background::from).or(standard.background), + border_radius: cosmic.radius_xs().into(), + border_width: 1.0, + border_color: cosmic.on_bg_color().into(), + outline_width, + outline_color, + icon_color: None, + text_color: None, + } + }), + pressed: Box::new(move |focused, theme| { + let cosmic = theme.cosmic(); + + let (outline_width, outline_color) = if focused { + (1.0, cosmic.accent_color().into()) + } else { + (0.0, Color::TRANSPARENT) + }; + + let standard = theme.pressed(focused, &Button::Standard); + button::Appearance { + shadow_offset: Vector::default(), + background: color.map(Background::from).or(standard.background), + border_radius: cosmic.radius_xs().into(), + border_width: 1.0, + border_color: cosmic.on_bg_color().into(), + outline_width, + outline_color, + icon_color: None, + text_color: None, + } + }), + }) } impl<'a, Message> From> for iced::Element<'a, Message, crate::Renderer>