when trying to set the style for a button by iced::widget::button("set 9991").style(style); I get:
.style(style)
| ----- ^^^^^ the trait `From<iced::application::Appearance>` is not implemented for `iced::theme::Button`, which is required by `iced::application::Appearance: Into<_>`
What can I do about that ?
style of type iced_widget::button::Appearance also does not work.
How to find out which types are allowed as argument for Button<_,_,>.style() ?
Edit:
let style = <Theme as iced_widget::button::StyleSheet>::Style::default();
compiles.
But I don’t understand this syntax and I don’t see how to change attributes w´in such kind of style.
use the iced crate as it is and build a “button color” functionality on top of it
locally modify the iced... crate and add support for the style() function allowing for providing more “user friendly” modification.
(2) certainly is harder, but could be evolve into a suggestion for enhancing the crate for many widgets, not just button.
Regarding the button color I just only tested the “active” appearance, but in the end a “user friendly” “current style” setting should/could modify all three appearances (active, hovered, pressed) at the same time in a consistent way.
Just raving…
Maybe an idea could be to try to do a “CommonWidgetStyle” type/trade for which a from function for all widgets could/should be implemented in a way that the (each optional) common style parameters are modified in a consistent way.
E.g.
With Container, a style() call with that type featuring a non Nonebackground_color would set the appearancebackground_color.
With Button, a style() call with non Nonebackground_color would set the appearance of the Active display to use that color, while trying to set the colors of the Pushed and Hovered variants in accordance to their previous relations to the previous Active color by some clever algorithm.
Ranting on…
I hae been able to do a my_sytyle() function in a trait that is added to Button, that takes a CommonWidgetStyle currently is just able to optionally modify the “active” color of the button.
With generic traits, overloading functions with different parameter types should be possible and the compiler should select the correct one when infering types (I did see examples and I seem to understand from() and into() work this way).
Unfortunately the additional my_style(self, value: CommonWidgetStyle) function I implemented using an additional trait trait MyStyle<TWidget> and which does work promisingly, can’t just be renamed to style(), as in that case the compiler uses the original function (which of course does result in an error, due to the type requested by that function is notCommonWidgetStyle) ).
Trying to do a style tweaker function that mixes new defined style elements with previously in the builder pattern defined style elements, I seemingly would need to get the previous elements out of the self parameter (here type Button). unfortunately I do not find a public member or a function that provides the current Theme / Stylesheet.
As style() is pub fn style(mut self, style: impl Into<Theme::Style>) it seems like I could implement a From<CommonWidgetStyle> / from() for Button<> to allow for my Style definition to be correctly passed into style().
But which types beside the full Button (which I seem to be not able to instanciate in some default way) do implement IntoTheme::Style) (and might be intended for such purpose ?
@prmthz
Using your suggestion as a startintg point I now was able to implementing an overriding feature for the style() function without modifying the library itself:
pub struct ColorButtonStyleSheet {
background_color: Color,
}
impl ColorButtonStyleSheet {
pub fn new(background_color: Color) -> iced::theme::Button {
iced::theme::Button::Custom(Box::new(Self { background_color }))
}
}
impl button::StyleSheet for ColorButtonStyleSheet {
type Style = iced::Theme;
fn active(&self, style: &Self::Style) -> button::Appearance {
let background = iced::Background::Color(self.background_color);
button::Appearance {
background: Some(background),
..Default::default()
}
}
fn hovered(&self, style: &Self::Style) -> button::Appearance {
let active = self.active(style);
let background = iced::Background::Color(Color::from_rgb(0.2, 0.2, 0.2)); // for testing
button::Appearance {
background: Some(background), // for testing
shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0), // todo: does not work
..active
}
}
fn pressed(&self, style: &Self::Style) -> button::Appearance {
button::Appearance {
shadow_offset: Vector::default(),
..self.active(style)
}
}
}
#[derive(Default)]
pub struct CommonWidgetStyle {
backgoud_color: Option<Color>,
}
impl From<CommonWidgetStyle> for iced::theme::Button {
fn from(value: CommonWidgetStyle) -> Self {
if value.backgoud_color.is_some() {
let color = value
.backgoud_color
.unwrap_or(Color::from_rgb(0.1, 0.0, 0.0));
let element = ColorButtonStyleSheet::new(color);
element
} else {
let element = iced::theme::Button::Primary;
element
}
}
}
Now I can do
let biv = widget.button.view();
let element: iced_widget::core::Element<Message, Theme, Renderer>;
let style = ColorButtonStyleSheet::new(Color::from_rgb(0.5, 0.5, 0.5));
let biv = biv.style(style);
element = biv.into();
But this is not really satisfying, as it would be good if in the builder pattern style() (the overriden version) could be used to set some Elements of the style of the widget (e.g. color) and leave others as they have been set prior in the builder chain (usually some default).
For this either a different function / method would be necessary (IMHO not desirable) or style() itself could be in a trait to allow overriding it. Moreover in the self parameter the “current” style elements would be necessary to be extracted to copy them to the now XxStyleSheet (which I did not succed in finding out, supposedly this is why I can’t get the shaddow feature working for the hover).
What do you think ?