diff options
-rw-r--r-- | examples/component/src/main.rs | 4 | ||||
-rw-r--r-- | examples/pure/component/src/main.rs | 6 | ||||
-rw-r--r-- | examples/scrollable/src/style.rs | 6 | ||||
-rw-r--r-- | examples/styling/src/main.rs | 63 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 55 | ||||
-rw-r--r-- | pure/src/helpers.rs | 1 | ||||
-rw-r--r-- | pure/src/widget/text_input.rs | 26 | ||||
-rw-r--r-- | src/pure/widget.rs | 2 | ||||
-rw-r--r-- | src/widget.rs | 2 | ||||
-rw-r--r-- | style/src/text_input.rs | 76 | ||||
-rw-r--r-- | style/src/theme.rs | 85 | ||||
-rw-r--r-- | style/src/theme/palette.rs | 2 |
12 files changed, 145 insertions, 183 deletions
diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index ec7c658f..73bbbe35 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -95,7 +95,7 @@ mod numeric_input { for NumericInput<'a, Message> where Renderer: 'a + text::Renderer, - Renderer::Theme: button::StyleSheet, + Renderer::Theme: button::StyleSheet + text_input::StyleSheet, { type Event = Event; @@ -173,7 +173,7 @@ mod numeric_input { where Message: 'a, Renderer: text::Renderer + 'a, - Renderer::Theme: button::StyleSheet, + Renderer::Theme: button::StyleSheet + text_input::StyleSheet, { fn from(numeric_input: NumericInput<'a, Message>) -> Self { component::view(numeric_input) diff --git a/examples/pure/component/src/main.rs b/examples/pure/component/src/main.rs index 2c065231..31592dbf 100644 --- a/examples/pure/component/src/main.rs +++ b/examples/pure/component/src/main.rs @@ -89,7 +89,8 @@ mod numeric_input { impl<Message, Renderer> Component<Message, Renderer> for NumericInput<Message> where Renderer: text::Renderer + 'static, - Renderer::Theme: widget::button::StyleSheet, + Renderer::Theme: + widget::button::StyleSheet + widget::text_input::StyleSheet, { type State = (); type Event = Event; @@ -160,7 +161,8 @@ mod numeric_input { where Message: 'a, Renderer: 'static + text::Renderer, - Renderer::Theme: widget::button::StyleSheet, + Renderer::Theme: + widget::button::StyleSheet + widget::text_input::StyleSheet, { fn from(numeric_input: NumericInput<Message>) -> Self { pure::component(numeric_input) diff --git a/examples/scrollable/src/style.rs b/examples/scrollable/src/style.rs index e15bf125..64922ae4 100644 --- a/examples/scrollable/src/style.rs +++ b/examples/scrollable/src/style.rs @@ -43,12 +43,6 @@ mod dark { 0x3F as f32 / 255.0, ); - const SURFACE: Color = Color::from_rgb( - 0x40 as f32 / 255.0, - 0x44 as f32 / 255.0, - 0x4B as f32 / 255.0, - ); - const ACCENT: Color = Color::from_rgb( 0x6F as f32 / 255.0, 0xFF as f32 / 255.0, diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index 8cd17a6c..e2a4b492 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -77,8 +77,7 @@ impl Sandbox for Styling { Message::InputChanged, ) .padding(10) - .size(20) - .style(self.theme); + .size(20); let button = Button::new(&mut self.button, Text::new("Submit")) .padding(10) @@ -157,7 +156,7 @@ impl Sandbox for Styling { } mod style { - use iced::{scrollable, text_input}; + use iced::scrollable; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Theme { @@ -175,15 +174,6 @@ mod style { } } - impl<'a> From<Theme> for Box<dyn text_input::StyleSheet + 'a> { - fn from(theme: Theme) -> Self { - match theme { - Theme::Light => Default::default(), - Theme::Dark => dark::TextInput.into(), - } - } - } - impl<'a> From<Theme> for Box<dyn scrollable::StyleSheet + 'a> { fn from(theme: Theme) -> Self { match theme { @@ -194,7 +184,7 @@ mod style { } mod dark { - use iced::{scrollable, text_input, Color}; + use iced::{scrollable, Color}; const SURFACE: Color = Color::from_rgb( 0x40 as f32 / 255.0, @@ -202,12 +192,6 @@ mod style { 0x4B as f32 / 255.0, ); - const ACCENT: Color = Color::from_rgb( - 0x6F as f32 / 255.0, - 0xFF as f32 / 255.0, - 0xE9 as f32 / 255.0, - ); - const ACTIVE: Color = Color::from_rgb( 0x72 as f32 / 255.0, 0x89 as f32 / 255.0, @@ -220,47 +204,6 @@ mod style { 0xC4 as f32 / 255.0, ); - pub struct TextInput; - - impl text_input::StyleSheet for TextInput { - fn active(&self) -> text_input::Style { - text_input::Style { - background: SURFACE.into(), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } - - fn focused(&self) -> text_input::Style { - text_input::Style { - border_width: 1.0, - border_color: ACCENT, - ..self.active() - } - } - - fn hovered(&self) -> text_input::Style { - text_input::Style { - border_width: 1.0, - border_color: Color { a: 0.3, ..ACCENT }, - ..self.focused() - } - } - - fn placeholder_color(&self) -> Color { - Color::from_rgb(0.4, 0.4, 0.4) - } - - fn value_color(&self) -> Color { - Color::WHITE - } - - fn selection_color(&self) -> Color { - ACTIVE - } - } - pub struct Scrollable; impl scrollable::StyleSheet for Scrollable { diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 8230398c..d345cec3 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -24,7 +24,7 @@ use crate::{ Shell, Size, Vector, Widget, }; -pub use iced_style::text_input::{Style, StyleSheet}; +pub use iced_style::text_input::{Appearance, StyleSheet}; /// A field that can be filled with text. /// @@ -52,7 +52,11 @@ pub use iced_style::text_input::{Style, StyleSheet}; /// ``` ///  #[allow(missing_debug_implementations)] -pub struct TextInput<'a, Message, Renderer: text::Renderer> { +pub struct TextInput<'a, Message, Renderer> +where + Renderer: text::Renderer, + Renderer::Theme: StyleSheet, +{ state: &'a mut State, placeholder: String, value: Value, @@ -63,13 +67,14 @@ pub struct TextInput<'a, Message, Renderer: text::Renderer> { size: Option<u16>, on_change: Box<dyn Fn(String) -> Message + 'a>, on_submit: Option<Message>, - style_sheet: Box<dyn StyleSheet + 'a>, + style: <Renderer::Theme as StyleSheet>::Style, } impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> where Message: Clone, Renderer: text::Renderer, + Renderer::Theme: StyleSheet, { /// Creates a new [`TextInput`]. /// @@ -98,7 +103,7 @@ where size: None, on_change: Box::new(on_change), on_submit: None, - style_sheet: Default::default(), + style: Default::default(), } } @@ -143,9 +148,9 @@ where /// Sets the style of the [`TextInput`]. pub fn style( mut self, - style_sheet: impl Into<Box<dyn StyleSheet + 'a>>, + style: impl Into<<Renderer::Theme as StyleSheet>::Style>, ) -> Self { - self.style_sheet = style_sheet.into(); + self.style = style.into(); self } @@ -161,12 +166,14 @@ where pub fn draw( &self, renderer: &mut Renderer, + theme: &Renderer::Theme, layout: Layout<'_>, cursor_position: Point, value: Option<&Value>, ) { draw( renderer, + theme, layout, cursor_position, &self.state, @@ -175,7 +182,7 @@ where self.size, &self.font, self.is_secure, - self.style_sheet.as_ref(), + self.style, ) } } @@ -575,6 +582,7 @@ where /// [`Renderer`]: text::Renderer pub fn draw<Renderer>( renderer: &mut Renderer, + theme: &Renderer::Theme, layout: Layout<'_>, cursor_position: Point, state: &State, @@ -583,9 +591,10 @@ pub fn draw<Renderer>( size: Option<u16>, font: &Renderer::Font, is_secure: bool, - style_sheet: &dyn StyleSheet, + style: <Renderer::Theme as StyleSheet>::Style, ) where Renderer: text::Renderer, + Renderer::Theme: StyleSheet, { let secure_value = is_secure.then(|| value.secure()); let value = secure_value.as_ref().unwrap_or(&value); @@ -595,22 +604,22 @@ pub fn draw<Renderer>( let is_mouse_over = bounds.contains(cursor_position); - let style = if state.is_focused() { - style_sheet.focused() + let appearance = if state.is_focused() { + theme.focused(style) } else if is_mouse_over { - style_sheet.hovered() + theme.hovered(style) } else { - style_sheet.active() + theme.active(style) }; renderer.fill_quad( renderer::Quad { bounds, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, + border_radius: appearance.border_radius, + border_width: appearance.border_width, + border_color: appearance.border_color, }, - style.background, + appearance.background, ); let text = value.to_string(); @@ -642,7 +651,7 @@ pub fn draw<Renderer>( border_width: 0.0, border_color: Color::TRANSPARENT, }, - style_sheet.value_color(), + theme.value_color(style), )), offset, ) @@ -686,7 +695,7 @@ pub fn draw<Renderer>( border_width: 0.0, border_color: Color::TRANSPARENT, }, - style_sheet.selection_color(), + theme.selection_color(style), )), if end == right { right_offset @@ -714,9 +723,9 @@ pub fn draw<Renderer>( renderer.fill_text(Text { content: if text.is_empty() { placeholder } else { &text }, color: if text.is_empty() { - style_sheet.placeholder_color() + theme.placeholder_color(style) } else { - style_sheet.value_color() + theme.value_color(style) }, font: font.clone(), bounds: Rectangle { @@ -756,6 +765,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> where Message: Clone, Renderer: text::Renderer, + Renderer::Theme: StyleSheet, { fn width(&self) -> Length { self.width @@ -812,13 +822,13 @@ where fn draw( &self, renderer: &mut Renderer, - _theme: &Renderer::Theme, + theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, ) { - self.draw(renderer, layout, cursor_position, None) + self.draw(renderer, theme, layout, cursor_position, None) } } @@ -827,6 +837,7 @@ impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>> where Message: 'a + Clone, Renderer: 'a + text::Renderer, + Renderer::Theme: StyleSheet, { fn from( text_input: TextInput<'a, Message, Renderer>, diff --git a/pure/src/helpers.rs b/pure/src/helpers.rs index ebc8f14b..1d020b3c 100644 --- a/pure/src/helpers.rs +++ b/pure/src/helpers.rs @@ -142,6 +142,7 @@ pub fn text_input<'a, Message, Renderer>( where Message: Clone, Renderer: iced_native::text::Renderer, + Renderer::Theme: widget::text_input::StyleSheet, { widget::TextInput::new(placeholder, value, on_change) } diff --git a/pure/src/widget/text_input.rs b/pure/src/widget/text_input.rs index 7d768513..d3e642a5 100644 --- a/pure/src/widget/text_input.rs +++ b/pure/src/widget/text_input.rs @@ -10,7 +10,7 @@ use iced_native::text; use iced_native::widget::text_input; use iced_native::{Clipboard, Length, Padding, Point, Rectangle, Shell}; -pub use iced_style::text_input::{Style, StyleSheet}; +pub use iced_style::text_input::{Appearance, StyleSheet}; /// A field that can be filled with text. /// @@ -33,7 +33,11 @@ pub use iced_style::text_input::{Style, StyleSheet}; /// ``` ///  #[allow(missing_debug_implementations)] -pub struct TextInput<'a, Message, Renderer: text::Renderer> { +pub struct TextInput<'a, Message, Renderer> +where + Renderer: text::Renderer, + Renderer::Theme: StyleSheet, +{ placeholder: String, value: text_input::Value, is_secure: bool, @@ -43,13 +47,14 @@ pub struct TextInput<'a, Message, Renderer: text::Renderer> { size: Option<u16>, on_change: Box<dyn Fn(String) -> Message + 'a>, on_submit: Option<Message>, - style_sheet: Box<dyn StyleSheet + 'a>, + style: <Renderer::Theme as StyleSheet>::Style, } impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> where Message: Clone, Renderer: text::Renderer, + Renderer::Theme: StyleSheet, { /// Creates a new [`TextInput`]. /// @@ -71,7 +76,7 @@ where size: None, on_change: Box::new(on_change), on_submit: None, - style_sheet: Default::default(), + style: Default::default(), } } @@ -83,7 +88,7 @@ where /// Sets the [`Font`] of the [`TextInput`]. /// - /// [`Font`]: iced_native::text::Renderer::Font + /// [`Font`]: text::Renderer::Font pub fn font(mut self, font: Renderer::Font) -> Self { self.font = font; self @@ -116,9 +121,9 @@ where /// Sets the style of the [`TextInput`]. pub fn style( mut self, - style_sheet: impl Into<Box<dyn StyleSheet + 'a>>, + style: impl Into<<Renderer::Theme as StyleSheet>::Style>, ) -> Self { - self.style_sheet = style_sheet.into(); + self.style = style.into(); self } } @@ -127,7 +132,8 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> for TextInput<'a, Message, Renderer> where Message: Clone, - Renderer: iced_native::text::Renderer, + Renderer: text::Renderer, + Renderer::Theme: StyleSheet, { fn tag(&self) -> tree::Tag { tree::Tag::of::<text_input::State>() @@ -198,6 +204,7 @@ where ) { text_input::draw( renderer, + theme, layout, cursor_position, tree.state.downcast_ref::<text_input::State>(), @@ -206,7 +213,7 @@ where self.size, &self.font, self.is_secure, - self.style_sheet.as_ref(), + self.style, ) } @@ -227,6 +234,7 @@ impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>> where Message: 'a + Clone, Renderer: 'a + text::Renderer, + Renderer::Theme: StyleSheet, { fn from( text_input: TextInput<'a, Message, Renderer>, diff --git a/src/pure/widget.rs b/src/pure/widget.rs index de460bec..6ef9262f 100644 --- a/src/pure/widget.rs +++ b/src/pure/widget.rs @@ -120,7 +120,7 @@ pub mod text_input { //! Display fields that can be filled with text. use crate::Renderer; - pub use iced_pure::widget::text_input::{Style, StyleSheet}; + pub use iced_pure::widget::text_input::{Appearance, StyleSheet}; /// A field that can be filled with text. pub type TextInput<'a, Message, Theme> = diff --git a/src/widget.rs b/src/widget.rs index 4cbf02ef..8275f6e4 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -140,7 +140,7 @@ pub mod text_input { //! A [`TextInput`] has some local [`State`]. use crate::Renderer; - pub use iced_native::widget::text_input::{State, Style, StyleSheet}; + pub use iced_native::widget::text_input::{Appearance, State, StyleSheet}; /// A field that can be filled with text. pub type TextInput<'a, Message, Theme> = diff --git a/style/src/text_input.rs b/style/src/text_input.rs index 3d5817cc..af86617b 100644 --- a/style/src/text_input.rs +++ b/style/src/text_input.rs @@ -3,87 +3,31 @@ use iced_core::{Background, Color}; /// The appearance of a text input. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub background: Background, pub border_radius: f32, pub border_width: f32, pub border_color: Color, } -impl std::default::Default for Style { - fn default() -> Self { - Self { - background: Background::Color(Color::WHITE), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } -} - /// A set of rules that dictate the style of a text input. pub trait StyleSheet { + type Style: Default + Copy; + /// Produces the style of an active text input. - fn active(&self) -> Style; + fn active(&self, style: Self::Style) -> Appearance; /// Produces the style of a focused text input. - fn focused(&self) -> Style; + fn focused(&self, style: Self::Style) -> Appearance; - fn placeholder_color(&self) -> Color; + fn placeholder_color(&self, style: Self::Style) -> Color; - fn value_color(&self) -> Color; + fn value_color(&self, style: Self::Style) -> Color; - fn selection_color(&self) -> Color; + fn selection_color(&self, style: Self::Style) -> Color; /// Produces the style of an hovered text input. - fn hovered(&self) -> Style { - self.focused() - } -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Style { - Style { - background: Background::Color(Color::WHITE), - border_radius: 5.0, - border_width: 1.0, - border_color: Color::from_rgb(0.7, 0.7, 0.7), - } - } - - fn focused(&self) -> Style { - Style { - border_color: Color::from_rgb(0.5, 0.5, 0.5), - ..self.active() - } - } - - fn placeholder_color(&self) -> Color { - Color::from_rgb(0.7, 0.7, 0.7) - } - - fn value_color(&self) -> Color { - Color::from_rgb(0.3, 0.3, 0.3) - } - - fn selection_color(&self) -> Color { - Color::from_rgb(0.8, 0.8, 1.0) - } -} - -impl<'a> std::default::Default for Box<dyn StyleSheet + 'a> { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From<T> for Box<dyn StyleSheet + 'a> -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) + fn hovered(&self, style: Self::Style) -> Appearance { + self.focused(style) } } diff --git a/style/src/theme.rs b/style/src/theme.rs index b0846c0e..e1ac719e 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -10,6 +10,7 @@ use crate::progress_bar; use crate::radio; use crate::rule; use crate::slider; +use crate::text_input; use crate::toggler; use iced_core::{Background, Color}; @@ -152,22 +153,22 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.primary.strong, is_checked, ), Checkbox::Secondary => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.danger.base, is_checked, ), @@ -183,23 +184,23 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( - palette.background.strong, - palette.primary.strong, + palette.background.weak, + palette.primary.base, is_checked, ), Checkbox::Secondary => checkbox_appearance( - palette.background.strong, - palette.background.strong, + palette.background.weak, + palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( - palette.background.strong, - palette.success.strong, + palette.background.weak, + palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( - palette.background.strong, - palette.danger.strong, + palette.background.weak, + palette.danger.base, is_checked, ), } @@ -410,7 +411,7 @@ impl progress_bar::StyleSheet for Theme { let palette = self.extended_palette(); let from_palette = |bar: Color| progress_bar::Appearance { - background: palette.background.weak.color.into(), + background: palette.background.strong.color.into(), bar: bar.into(), border_radius: 2.0, }; @@ -456,3 +457,61 @@ impl rule::StyleSheet for Theme { } } } + +/* + * Text Input + */ +impl text_input::StyleSheet for Theme { + type Style = (); + + fn active(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.strong.color, + } + } + + fn hovered(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.base.text, + } + } + + fn focused(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.primary.strong.color, + } + } + + fn placeholder_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.background.strong.color + } + + fn value_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.background.base.text + } + + fn selection_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.primary.weak.color + } +} diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index 3d1ca097..fb23bb42 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -120,7 +120,7 @@ pub struct Background { impl Background { pub fn new(base: Color, text: Color) -> Self { let weak = mix(base, text, 0.15); - let strong = mix(base, text, 0.25); + let strong = mix(base, text, 0.40); Self { base: Pair::new(base, text), |