diff options
Diffstat (limited to 'native/src/widget')
-rw-r--r-- | native/src/widget/checkbox.rs | 38 | ||||
-rw-r--r-- | native/src/widget/container.rs | 53 | ||||
-rw-r--r-- | native/src/widget/pick_list.rs | 131 | ||||
-rw-r--r-- | native/src/widget/scrollable.rs | 19 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 2 |
5 files changed, 159 insertions, 84 deletions
diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index b46433c2..f6298a8c 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -14,6 +14,17 @@ use crate::{ pub use iced_style::checkbox::{Appearance, StyleSheet}; +/// The icon in a [`Checkbox`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Icon<Font> { + /// Font that will be used to display the `code_point`, + pub font: Font, + /// The unicode code point that will be used as the icon. + pub code_point: char, + /// Font size of the content. + pub size: Option<u16>, +} + /// A box that can be checked. /// /// # Example @@ -45,6 +56,7 @@ where spacing: u16, text_size: Option<u16>, font: Renderer::Font, + icon: Icon<Renderer::Font>, style: <Renderer::Theme as StyleSheet>::Style, } @@ -80,6 +92,11 @@ where spacing: Self::DEFAULT_SPACING, text_size: None, font: Renderer::Font::default(), + icon: Icon { + font: Renderer::ICON_FONT, + code_point: Renderer::CHECKMARK_ICON, + size: None, + }, style: Default::default(), } } @@ -116,6 +133,12 @@ where self } + /// Sets the [`Icon`] of the [`Checkbox`]. + pub fn icon(mut self, icon: Icon<Renderer::Font>) -> Self { + self.icon = icon; + self + } + /// Sets the style of the [`Checkbox`]. pub fn style( mut self, @@ -243,17 +266,24 @@ where custom_style.background, ); + let Icon { + font, + code_point, + size, + } = &self.icon; + let size = size.map(f32::from).unwrap_or(bounds.height * 0.7); + if self.is_checked { renderer.fill_text(text::Text { - content: &Renderer::CHECKMARK_ICON.to_string(), - font: Renderer::ICON_FONT, - size: bounds.height * 0.7, + content: &code_point.to_string(), + font: font.clone(), + size, bounds: Rectangle { x: bounds.center_x(), y: bounds.center_y(), ..bounds }, - color: custom_style.checkmark_color, + color: custom_style.icon_color, horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Center, }); diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index cdf1c859..c82b8be2 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -5,7 +5,7 @@ use crate::layout; use crate::mouse; use crate::overlay; use crate::renderer; -use crate::widget::{Operation, Tree}; +use crate::widget::{self, Operation, Tree}; use crate::{ Background, Clipboard, Color, Element, Layout, Length, Padding, Point, Rectangle, Shell, Widget, @@ -24,6 +24,7 @@ where Renderer: crate::Renderer, Renderer::Theme: StyleSheet, { + id: Option<Id>, padding: Padding, width: Length, height: Length, @@ -46,6 +47,7 @@ where T: Into<Element<'a, Message, Renderer>>, { Container { + id: None, padding: Padding::ZERO, width: Length::Shrink, height: Length::Shrink, @@ -58,6 +60,12 @@ where } } + /// Sets the [`Id`] of the [`Container`]. + pub fn id(mut self, id: Id) -> Self { + self.id = Some(id); + self + } + /// Sets the [`Padding`] of the [`Container`]. pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self { self.padding = padding.into(); @@ -172,14 +180,17 @@ where renderer: &Renderer, operation: &mut dyn Operation<Message>, ) { - operation.container(None, &mut |operation| { - self.content.as_widget().operate( - &mut tree.children[0], - layout.children().next().unwrap(), - renderer, - operation, - ); - }); + operation.container( + self.id.as_ref().map(|id| &id.0), + &mut |operation| { + self.content.as_widget().operate( + &mut tree.children[0], + layout.children().next().unwrap(), + renderer, + operation, + ); + }, + ); } fn on_event( @@ -333,3 +344,27 @@ pub fn draw_background<Renderer>( ); } } + +/// The identifier of a [`Container`]. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Id(widget::Id); + +impl Id { + /// Creates a custom [`Id`]. + pub fn new(id: impl Into<std::borrow::Cow<'static, str>>) -> Self { + Self(widget::Id::new(id)) + } + + /// Creates a unique [`Id`]. + /// + /// This function produces a different [`Id`] every time it is called. + pub fn unique() -> Self { + Self(widget::Id::unique()) + } +} + +impl From<Id> for widget::Id { + fn from(id: Id) -> Self { + id.0 + } +} diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index c2853314..b1cdfad4 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -20,60 +20,6 @@ use std::borrow::Cow; pub use iced_style::pick_list::{Appearance, StyleSheet}; -/// The handle to the right side of the [`PickList`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Handle<Renderer> -where - Renderer: text::Renderer, -{ - /// Displays an arrow icon (▼). - /// - /// This is the default. - Arrow { - /// Font size of the content. - size: Option<u16>, - }, - /// A custom handle. - Custom { - /// Font that will be used to display the `text`, - font: Renderer::Font, - /// Text that will be shown. - text: String, - /// Font size of the content. - size: Option<u16>, - }, - /// No handle will be shown. - None, -} - -impl<Renderer> Default for Handle<Renderer> -where - Renderer: text::Renderer, -{ - fn default() -> Self { - Self::Arrow { size: None } - } -} - -impl<Renderer> Handle<Renderer> -where - Renderer: text::Renderer, -{ - fn content(&self) -> Option<(Renderer::Font, String, Option<u16>)> { - match self { - Self::Arrow { size } => Some(( - Renderer::ICON_FONT, - Renderer::ARROW_DOWN_ICON.to_string(), - *size, - )), - Self::Custom { font, text, size } => { - Some((font.clone(), text.clone(), *size)) - } - Self::None => None, - } - } -} - /// A widget for selecting a single value from a list of options. #[allow(missing_debug_implementations)] pub struct PickList<'a, T, Message, Renderer> @@ -90,7 +36,7 @@ where padding: Padding, text_size: Option<u16>, font: Renderer::Font, - handle: Handle<Renderer>, + handle: Handle<Renderer::Font>, style: <Renderer::Theme as StyleSheet>::Style, } @@ -161,7 +107,7 @@ where } /// Sets the [`Handle`] of the [`PickList`]. - pub fn handle(mut self, handle: Handle<Renderer>) -> Self { + pub fn handle(mut self, handle: Handle<Renderer::Font>) -> Self { self.handle = handle; self } @@ -258,7 +204,7 @@ where fn draw( &self, - _tree: &Tree, + tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, _style: &renderer::Style, @@ -278,6 +224,7 @@ where self.selected.as_ref(), &self.handle, &self.style, + || tree.state.downcast_ref::<State<T>>(), ) } @@ -349,6 +296,46 @@ impl<T> Default for State<T> { } } +/// The handle to the right side of the [`PickList`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Handle<Font> { + /// Displays an arrow icon (▼). + /// + /// This is the default. + Arrow { + /// Font size of the content. + size: Option<u16>, + }, + /// A custom static handle. + Static(Icon<Font>), + /// A custom dynamic handle. + Dynamic { + /// The [`Icon`] used when [`PickList`] is closed. + closed: Icon<Font>, + /// The [`Icon`] used when [`PickList`] is open. + open: Icon<Font>, + }, + /// No handle will be shown. + None, +} + +impl<Font> Default for Handle<Font> { + fn default() -> Self { + Self::Arrow { size: None } + } +} + +/// The icon of a [`Handle`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Icon<Font> { + /// Font that will be used to display the `code_point`, + pub font: Font, + /// The unicode code point that will be used as the icon. + pub code_point: char, + /// Font size of the content. + pub size: Option<u16>, +} + /// Computes the layout of a [`PickList`]. pub fn layout<Renderer, T>( renderer: &Renderer, @@ -568,7 +555,7 @@ where } /// Draws a [`PickList`]. -pub fn draw<T, Renderer>( +pub fn draw<'a, T, Renderer>( renderer: &mut Renderer, theme: &Renderer::Theme, layout: Layout<'_>, @@ -578,12 +565,13 @@ pub fn draw<T, Renderer>( font: &Renderer::Font, placeholder: Option<&str>, selected: Option<&T>, - handle: &Handle<Renderer>, + handle: &Handle<Renderer::Font>, style: &<Renderer::Theme as StyleSheet>::Style, + state: impl FnOnce() -> &'a State<T>, ) where Renderer: text::Renderer, Renderer::Theme: StyleSheet, - T: ToString, + T: ToString + 'a, { let bounds = layout.bounds(); let is_mouse_over = bounds.contains(cursor_position); @@ -605,11 +593,30 @@ pub fn draw<T, Renderer>( style.background, ); - if let Some((font, text, size)) = handle.content() { + let handle = match handle { + Handle::Arrow { size } => { + Some((Renderer::ICON_FONT, Renderer::ARROW_DOWN_ICON, *size)) + } + Handle::Static(Icon { + font, + code_point, + size, + }) => Some((font.clone(), *code_point, *size)), + Handle::Dynamic { open, closed } => { + if state().is_open { + Some((open.font.clone(), open.code_point, open.size)) + } else { + Some((closed.font.clone(), closed.code_point, closed.size)) + } + } + Handle::None => None, + }; + + if let Some((font, code_point, size)) = handle { let size = f32::from(size.unwrap_or_else(|| renderer.default_size())); renderer.fill_text(Text { - content: &text, + content: &code_point.to_string(), size, font, color: style.handle_color, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 82286036..2de722e4 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -208,14 +208,17 @@ where operation.scrollable(state, self.id.as_ref().map(|id| &id.0)); - operation.container(None, &mut |operation| { - self.content.as_widget().operate( - &mut tree.children[0], - layout.children().next().unwrap(), - renderer, - operation, - ); - }); + operation.container( + self.id.as_ref().map(|id| &id.0), + &mut |operation| { + self.content.as_widget().operate( + &mut tree.children[0], + layout.children().next().unwrap(), + renderer, + operation, + ); + }, + ); } fn on_event( diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 8755b85d..5bfc918c 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -389,8 +389,8 @@ where let padding = padding.fit(Size::ZERO, limits.max()); let limits = limits - .pad(padding) .width(width) + .pad(padding) .height(Length::Units(text_size)); let mut text = layout::Node::new(limits.resolve(Size::ZERO)); |