🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2023-11-02 2:23:31.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-11-02 2:41:14.0 +00:00:00
commit
721146d45475861794d0d8171cdbaf514a26a83a [patch]
tree
9dada1745c2ecf3eb9b3cb44734d94bbf2da0744
parent
ef05d0776e5b0e1afe447056dffa3e79e9470df9
download
721146d45475861794d0d8171cdbaf514a26a83a.tar.gz

Round corners on colour picker



Diff

 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(-)

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<Event> {
    hue: f32,
    saturation: f32,
@@ -51,23 +53,29 @@ impl<Event> Component<Event, Renderer> for ColourPicker<Event> {
    }

    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<Message> canvas::Program<Message> for HueSlider<Message> {
            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<Message> canvas::Program<Message> for HueSlider<Message> {
                    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<Message> canvas::Program<Message> for HueSlider<Message> {

                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<M, R> 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<Tree> {
        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<M>,
    ) {
        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<Element<'b, M, R>> {
        Some(overlay::Element::new(
            layout.position(),
            Box::new(Overlay {
                size: layout.bounds().size(),
                position: Some(layout.bounds().position()),
            }),
        ))
    }
}

impl<'a, M, R> From<ForcedRounded<'a, M, R>> 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<Point>,
}

impl<M, R: Renderer> overlay::Overlay<M, R> 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<M, Renderer> for ImageCard<'a, M> {
        layout: Layout<'_>,
        _renderer: &Renderer,
    ) -> Option<iced::advanced::overlay::Element<'b, M, Renderer>> {
        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;