New styling API (0.13) inside of a function

So I am creating a function that returns an Element. Which works perfectly fine, it has the trait restrictions:

where
    Message: 'a + Clone,
    Theme: 'a + button::Catalog + iced::widget::text::Catalog,
    Renderer: 'a + iced::advanced::Renderer + iced::advanced::text::Renderer,

And when I attempt to apply some of my custom styles, like this:

pub fn punge_button_style(status: Status) -> Style {
    match status {
        Status::Disabled => Style {
            background: None,
            text_color: Color {
                r: 0.85,
                g: 0.85,
                b: 0.85,
                a: 1.0,
            },
            border: Border {
                color: Color {
                    r: 0.0,
                    g: 0.0,
                    b: 0.0,
                    a: 0.0,
                },
                radius: Radius::default(),
                width: 1.0,
            },
            shadow: Shadow::default(),
        },

        _ => Style::default(),
    }
}

I get an error:

.style(|_t, status| punge_button_style(status))
^^^^^ the trait `From<std::boxed::Box<dyn for<'a> std::ops::Fn(&'a Theme, iced::widget::button::Status) -> iced::widget::button::Style>>` is not implemented for `<Theme as iced::widget::button::Catalog>::Class<'_>`

note: required by a bound in `iced::widget::Button::<'a, Message, Theme, Renderer>::style`

I’ve searched through to try to find examples of people doing similar things, but I haven’t found many projects that have upgraded to the new styling api. (given it hasn’t had a release yet).

Again, this works fine when I use my styling in my view function, but doesn’t seem to like being in a regular function. Any help would be great!

Can you share you full code, so we can run it by our self and play with it?

Where do these restrictions come from?

where
Message: 'a + Clone,
Theme: 'a + button::Catalog + iced::widget::text::Catalog,
Renderer: 'a + iced::advanced::Renderer + iced::advanced::text::Renderer,

Here, this replicates the problem I had:

use iced::border::{Border, Radius};
use iced::widget::button::{Status, Style};
use iced::widget::{button, container, row, text};
use iced::Element;
use iced::{Color, Shadow};

fn main() -> iced::Result {
    iced::run("testing", App::update, App::view)
}

#[derive(Default)]
struct App {}

#[derive(Debug, Clone)]
enum Message {
    Test,
}

fn create_stuff<'a, Message, Theme, Renderer>() -> Element<'a, Message, Theme, Renderer>
where
    Message: 'a + Clone,
    Theme: 'a + button::Catalog + iced::widget::text::Catalog,
    Renderer: 'a + iced::advanced::Renderer + iced::advanced::text::Renderer,
{
    row![button(text("here is some content!!")).style(|_t, status| custom_button(status))].into()
}

impl App {
    fn update(&mut self, message: Message) {
        println!("ignore")
    }

    fn view(&self) -> Element<Message> {
        container(row![
            button(text("my content!")).style(|_t, status| custom_button(status)),
            create_stuff(),
        ])
        .into()
    }
}

fn custom_button(status: iced::widget::button::Status) -> iced::widget::button::Style {
    match status {
        Status::Disabled => Style {
            background: None,
            text_color: Color {
                r: 0.85,
                g: 0.85,
                b: 0.85,
                a: 1.0,
            },
            border: Border {
                color: Color {
                    r: 0.0,
                    g: 0.0,
                    b: 0.0,
                    a: 0.0,
                },
                radius: Radius::default(),
                width: 1.0,
            },
            shadow: Shadow::default(),
        },

        _ => Style::default(),
    }
}

With the iced version being:

iced = {git = "https://github.com/iced-rs/iced", branch = "feature/list-widget-reloaded", features = ["advanced"] }

(using the master branch caused some dependency errors for me, I’m not sure if there is a different specific 0.13 branch, but the one I use has the styling changes)

The style methods need additional bounds:

pub fn style(
    self,
    style: impl Fn(&Theme, Status) -> Style + 'a,
) -> Button<'a, Message, Theme, Renderer>
where
    <Theme as Catalog>::Class<'a>: From<Box<dyn Fn(&Theme, Status) -> Style + 'a>>,

Make sure you add them.

I got it.

Was sort of confused as what Catalog refers to (I recall people making their own trait for it).

fn create_stuff<'a, Message, Theme, Renderer>() -> Element<'a, Message, Theme, Renderer>
where
    <Theme as iced::widget::button::Catalog>::Class<'a>:
        From<Box<dyn Fn(&Theme, Status) -> Style + 'a>>,
    Message: 'a + Clone,
    Theme: 'a + button::Catalog + iced::widget::text::Catalog,
    Renderer: 'a + iced::advanced::Renderer + iced::advanced::text::Renderer,
{

Was all it needed.

Thanks!