From 721146d45475861794d0d8171cdbaf514a26a83a Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 2 Nov 2023 02:23:31 +0000 Subject: [PATCH] Round corners on colour picker --- shalom/src/widgets/colour_picker.rs | 60 ++++++++++++++++++++++++++++++++++-------------------------- shalom/src/widgets/forced_rounded.rs | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ shalom/src/widgets/image_card.rs | 30 +++++++++++++++++++++--------- shalom/src/widgets/mod.rs | 1 + 4 files changed, 235 insertions(+), 35 deletions(-) create mode 100644 shalom/src/widgets/forced_rounded.rs diff --git a/shalom/src/widgets/colour_picker.rs b/shalom/src/widgets/colour_picker.rs index cb4579a..863e868 100644 --- a/shalom/src/widgets/colour_picker.rs +++ b/shalom/src/widgets/colour_picker.rs @@ -7,11 +7,13 @@ use iced::{ widget::{ canvas, canvas::{Cache, Event, Frame, Geometry, Path, Stroke, Style}, - component, Column, Component, + component, Component, Row, }, Color, Point, Rectangle, Renderer, Size, Theme, }; +use crate::widgets::forced_rounded::forced_rounded; + pub struct ColourPicker { hue: f32, saturation: f32, @@ -51,23 +53,29 @@ impl Component for ColourPicker { } fn view(&self, _state: &Self::State) -> Element<'_, Self::Event, Renderer> { - let saturation_brightness_picker = canvas(SaturationBrightnessPicker::new( - self.hue, - self.saturation, - self.brightness, - Message::OnSaturationBrightnessChange, - )) - .height(192) - .width(192); - - let hue_slider = canvas(HueSlider::new(self.hue, Message::OnHueChanged)) - .height(24) - .width(192); - - Column::new() + let saturation_brightness_picker = forced_rounded( + canvas(SaturationBrightnessPicker::new( + self.hue, + self.saturation, + self.brightness, + Message::OnSaturationBrightnessChange, + )) + .height(192) + .width(192) + .into(), + ); + + let hue_slider = forced_rounded( + canvas(HueSlider::new(self.hue, Message::OnHueChanged)) + .height(192) + .width(32) + .into(), + ); + + Row::new() .push(saturation_brightness_picker) .push(hue_slider) - .spacing(4) + .spacing(0) .into() } } @@ -134,7 +142,7 @@ impl canvas::Program for HueSlider { if let Some(position) = cursor.position_in(bounds) { state.arrow_cache.clear(); - let hue = (position.x / bounds.width) * 360.; + let hue = (position.y / bounds.height) * 360.; (Status::Captured, Some((self.on_hue_change)(hue))) } else { (Status::Captured, None) @@ -163,12 +171,12 @@ impl canvas::Program for HueSlider { clippy::cast_sign_loss, clippy::cast_precision_loss )] - for x in 0..size.width as u32 { - let hue = (x as f32 / size.width) * 360.0; + for y in 0..size.height as u32 { + let hue = (y as f32 / size.height) * 360.0; let color = colour_from_hsb(hue, 1.0, 1.0); frame.fill_rectangle( - Point::new(x as f32, 0.0), - Size::new(1.0, size.height), + Point::new(0.0, y as f32), + Size::new(size.width, 1.0), color, ); } @@ -182,15 +190,15 @@ impl canvas::Program for HueSlider { let arrow_width = 10.0; let arrow_height = 10.0; - let arrow_x = (self.hue / 360.0) * size.width - (arrow_width / 2.0); - let arrow_y = size.height - arrow_height; + let arrow_x = size.width; + let arrow_y = (self.hue / 360.0) * size.height - (arrow_height / 2.0); let arrow = Path::new(|p| { p.move_to(Point::new(arrow_x, arrow_y)); - p.line_to(Point::new(arrow_x + arrow_width, arrow_y)); + p.line_to(Point::new(arrow_x, arrow_y - arrow_width)); p.line_to(Point::new( - arrow_x + (arrow_width / 2.0), - arrow_y + arrow_height, + arrow_x - arrow_height, + arrow_y - (arrow_width / 2.0), )); p.line_to(Point::new(arrow_x, arrow_y)); p.close(); diff --git a/shalom/src/widgets/forced_rounded.rs b/shalom/src/widgets/forced_rounded.rs new file mode 100644 index 0000000..dfb19c6 --- /dev/null +++ b/shalom/src/widgets/forced_rounded.rs @@ -0,0 +1,179 @@ +use iced::{ + advanced::{ + layout::{Limits, Node}, + overlay, + overlay::Element, + renderer::{Quad, Style}, + widget::{ + tree::{State, Tag}, + Operation, Tree, + }, + Clipboard, Layout, Renderer, Shell, Widget, + }, + event::Status, + mouse::{Cursor, Interaction}, + Background, Color, Event, Length, Point, Rectangle, Size, +}; + +pub fn forced_rounded<'a, M: 'a, R>(element: iced::Element<'a, M, R>) -> ForcedRounded<'a, M, R> { + ForcedRounded { element } +} + +pub struct ForcedRounded<'a, M, R> { + element: iced::Element<'a, M, R>, +} + +impl<'a, M, R: Renderer> Widget for ForcedRounded<'a, M, R> { + fn width(&self) -> Length { + self.element.as_widget().width() + } + + fn height(&self) -> Length { + self.element.as_widget().height() + } + + fn layout(&self, renderer: &R, limits: &Limits) -> Node { + self.element.as_widget().layout(renderer, limits) + } + + fn draw( + &self, + state: &Tree, + renderer: &mut R, + theme: &R::Theme, + style: &Style, + layout: Layout<'_>, + cursor: Cursor, + viewport: &Rectangle, + ) { + self.element + .as_widget() + .draw(state, renderer, theme, style, layout, cursor, viewport); + } + + fn tag(&self) -> Tag { + self.element.as_widget().tag() + } + + fn children(&self) -> Vec { + self.element.as_widget().children() + } + + fn diff(&self, tree: &mut Tree) { + self.element.as_widget().diff(tree); + } + + fn mouse_interaction( + &self, + state: &Tree, + layout: Layout<'_>, + cursor: Cursor, + viewport: &Rectangle, + renderer: &R, + ) -> Interaction { + self.element + .as_widget() + .mouse_interaction(state, layout, cursor, viewport, renderer) + } + + fn on_event( + &mut self, + state: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor: Cursor, + renderer: &R, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, M>, + viewport: &Rectangle, + ) -> Status { + self.element.as_widget_mut().on_event( + state, event, layout, cursor, renderer, clipboard, shell, viewport, + ) + } + + fn operate( + &self, + state: &mut Tree, + layout: Layout<'_>, + renderer: &R, + operation: &mut dyn Operation, + ) { + self.element + .as_widget() + .operate(state, layout, renderer, operation); + } + + fn state(&self) -> State { + self.element.as_widget().state() + } + + fn overlay<'b>( + &'b mut self, + _state: &'b mut Tree, + layout: Layout<'_>, + _renderer: &R, + ) -> Option> { + Some(overlay::Element::new( + layout.position(), + Box::new(Overlay { + size: layout.bounds().size(), + position: Some(layout.bounds().position()), + }), + )) + } +} + +impl<'a, M, R> From> for iced::Element<'a, M, R> +where + M: 'a + Clone, + R: 'a + Renderer, +{ + fn from(e: ForcedRounded<'a, M, R>) -> Self { + iced::Element::new(e) + } +} + +pub struct Overlay { + pub size: Size, + pub position: Option, +} + +impl overlay::Overlay for Overlay { + fn layout(&self, _renderer: &R, _bounds: Size, position: Point) -> Node { + let mut node = Node::new(self.size); + node.move_to(self.position.unwrap_or(position)); + + node + } + + fn draw( + &self, + renderer: &mut R, + _theme: &R::Theme, + _style: &Style, + layout: Layout<'_>, + _cursor: Cursor, + ) { + renderer.with_layer(layout.bounds(), |renderer| { + renderer.fill_quad( + Quad { + bounds: Rectangle { + height: self.size.height + 12., + width: self.size.width + 12., + x: layout.bounds().x - 6., + y: layout.bounds().y - 6., + }, + border_radius: [20., 20., 20., 20.].into(), + border_width: 10., + border_color: Color::WHITE, + }, + Background::Color(Color::TRANSPARENT), + ); + }); + } + + fn is_over(&self, _layout: Layout<'_>, _renderer: &R, _cursor_position: Point) -> bool { + false + } +} diff --git a/shalom/src/widgets/image_card.rs b/shalom/src/widgets/image_card.rs index 6959f54..2f82ea5 100644 --- a/shalom/src/widgets/image_card.rs +++ b/shalom/src/widgets/image_card.rs @@ -122,15 +122,27 @@ impl<'a, M: Clone> Widget for ImageCard<'a, M> { layout: Layout<'_>, _renderer: &Renderer, ) -> Option> { - Some(overlay::Element::new( - layout.position(), - Box::new(Overlay { - text: &mut self.text, - tree: &mut state.children[0], - size: layout.bounds().size(), - on_press: self.on_press.as_ref(), - }), - )) + Some( + overlay::Group::with_children(vec![ + overlay::Element::new( + layout.position(), + Box::new(super::forced_rounded::Overlay { + size: layout.bounds().size(), + position: None, + }), + ), + overlay::Element::new( + layout.position(), + Box::new(Overlay { + text: &mut self.text, + tree: &mut state.children[0], + size: layout.bounds().size(), + on_press: self.on_press.as_ref(), + }), + ), + ]) + .overlay(), + ) } } diff --git a/shalom/src/widgets/mod.rs b/shalom/src/widgets/mod.rs index 44f9171..16108ee 100644 --- a/shalom/src/widgets/mod.rs +++ b/shalom/src/widgets/mod.rs @@ -1,6 +1,7 @@ pub mod cards; pub mod colour_picker; pub mod context_menu; +pub mod forced_rounded; pub mod image_card; pub mod media_player; pub mod mouse_area; -- libgit2 1.7.2