From 03b34931383e701c39c653a7662a616fe21a0947 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 16:07:22 +0700 Subject: Remove trait-specific draw logic in `iced_native` --- native/src/widget/button.rs | 25 +---- native/src/widget/checkbox.rs | 74 +++++--------- native/src/widget/column.rs | 37 +------ native/src/widget/container.rs | 24 +---- native/src/widget/image.rs | 7 +- native/src/widget/image/viewer.rs | 47 +-------- native/src/widget/pane_grid.rs | 170 ++++++++++--------------------- native/src/widget/pane_grid/content.rs | 53 +++++----- native/src/widget/pane_grid/title_bar.rs | 56 +++++----- native/src/widget/pick_list.rs | 27 +---- native/src/widget/progress_bar.rs | 25 +---- native/src/widget/radio.rs | 74 ++++++-------- native/src/widget/row.rs | 44 ++------ native/src/widget/rule.rs | 18 +--- native/src/widget/scrollable.rs | 117 ++++++++------------- native/src/widget/slider.rs | 43 +++----- native/src/widget/space.rs | 15 +-- native/src/widget/svg.rs | 8 +- native/src/widget/text.rs | 40 +------- native/src/widget/text_input.rs | 89 +++++++--------- native/src/widget/toggler.rs | 88 ++++++---------- native/src/widget/tooltip.rs | 43 ++------ 22 files changed, 327 insertions(+), 797 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index c469a0e5..1c7f80ef 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -248,17 +248,7 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - defaults, - layout.bounds(), - cursor_position, - self.on_press.is_none(), - self.state.is_pressed, - &self.style, - &self.content, - layout.children().next().unwrap(), - ) + ) { } fn hash_layout(&self, state: &mut Hasher) { @@ -289,19 +279,6 @@ pub trait Renderer: crate::Renderer + Sized { /// The style supported by this renderer. type Style: Default; - - /// Draws a [`Button`]. - fn draw( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - cursor_position: Point, - is_disabled: bool, - is_pressed: bool, - style: &Self::Style, - content: &Element<'_, Message, Self>, - content_layout: Layout<'_>, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 8bdb6b78..579e4ee3 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -5,7 +5,6 @@ use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; use crate::mouse; -use crate::row; use crate::text; use crate::touch; use crate::{ @@ -121,7 +120,7 @@ impl impl Widget for Checkbox where - Renderer: self::Renderer + text::Renderer + row::Renderer, + Renderer: self::Renderer + text::Renderer, { fn width(&self) -> Length { self.width @@ -187,36 +186,29 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - let bounds = layout.bounds(); - let mut children = layout.children(); - - let checkbox_layout = children.next().unwrap(); - let label_layout = children.next().unwrap(); - let checkbox_bounds = checkbox_layout.bounds(); - - let label = text::Renderer::draw( - renderer, - defaults, - label_layout.bounds(), - &self.label, - self.text_size.unwrap_or(renderer.default_size()), - self.font, - self.text_color, - alignment::Horizontal::Left, - alignment::Vertical::Center, - ); - - let is_mouse_over = bounds.contains(cursor_position); - - self::Renderer::draw( - renderer, - checkbox_bounds, - self.is_checked, - is_mouse_over, - label, - &self.style, - ) + ) { + // let bounds = layout.bounds(); + // let mut children = layout.children(); + + // let checkbox_layout = children.next().unwrap(); + // let label_layout = children.next().unwrap(); + // let checkbox_bounds = checkbox_layout.bounds(); + + // let label = text::Renderer::draw( + // renderer, + // defaults, + // label_layout.bounds(), + // &self.label, + // self.text_size.unwrap_or(renderer.default_size()), + // self.font, + // self.text_color, + // alignment::Horizontal::Left, + // alignment::Vertical::Center, + // ); + + // let is_mouse_over = bounds.contains(cursor_position); + + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -242,28 +234,12 @@ pub trait Renderer: crate::Renderer { /// The default spacing of a [`Checkbox`]. const DEFAULT_SPACING: u16; - - /// Draws a [`Checkbox`]. - /// - /// It receives: - /// * the bounds of the [`Checkbox`] - /// * whether the [`Checkbox`] is selected or not - /// * whether the mouse is over the [`Checkbox`] or not - /// * the drawn label of the [`Checkbox`] - fn draw( - &mut self, - bounds: Rectangle, - is_checked: bool, - is_mouse_over: bool, - label: Self::Output, - style: &Self::Style, - ) -> Self::Output; } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + text::Renderer + row::Renderer, + Renderer: 'a + self::Renderer + text::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 30cf0781..61b2361f 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -105,7 +105,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget for Column<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -169,14 +169,8 @@ where layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - defaults, - &self.children, - layout, - cursor_position, - viewport, - ) + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -208,33 +202,10 @@ where } } -/// The renderer of a [`Column`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Column`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// Draws a [`Column`]. - /// - /// It receives: - /// - the children of the [`Column`] - /// - the [`Layout`] of the [`Column`] and its children - /// - the cursor position - fn draw( - &mut self, - defaults: &Self::Defaults, - content: &[Element<'_, Message, Self>], - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - ) -> Self::Output; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 0e86ab62..f43de2a5 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -179,16 +179,8 @@ where layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - defaults, - layout.bounds(), - cursor_position, - viewport, - &self.style, - &self.content, - layout.children().next().unwrap(), - ) + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -221,18 +213,6 @@ where pub trait Renderer: crate::Renderer { /// The style supported by this renderer. type Style: Default; - - /// Draws a [`Container`]. - fn draw( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - cursor_position: Point, - viewport: &Rectangle, - style: &Self::Style, - content: &Element<'_, Message, Self>, - content_layout: Layout<'_>, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 4d8e0a3f..1607a596 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -96,8 +96,8 @@ where layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw(self.handle.clone(), layout) + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -225,9 +225,6 @@ impl std::fmt::Debug for Data { pub trait Renderer: crate::Renderer { /// Returns the dimensions of an [`Image`] located on the given path. fn dimensions(&self, handle: &Handle) -> (u32, u32); - - /// Draws an [`Image`]. - fn draw(&mut self, handle: Handle, layout: Layout<'_>) -> Self::Output; } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index 405daf00..d483ed61 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -88,7 +88,7 @@ impl<'a> Viewer<'a> { /// will be respected. fn image_size(&self, renderer: &Renderer, bounds: Size) -> Size where - Renderer: self::Renderer + image::Renderer, + Renderer: image::Renderer, { let (width, height) = renderer.dimensions(&self.handle); @@ -115,7 +115,7 @@ impl<'a> Viewer<'a> { impl<'a, Message, Renderer> Widget for Viewer<'a> where - Renderer: self::Renderer + image::Renderer, + Renderer: image::Renderer, { fn width(&self) -> Length { self.width @@ -287,7 +287,7 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { + ) { let bounds = layout.bounds(); let image_size = self.image_size(renderer, bounds.size()); @@ -302,16 +302,6 @@ where }; let is_mouse_over = bounds.contains(cursor_position); - - self::Renderer::draw( - renderer, - &self.state, - bounds, - image_size, - translation, - self.handle.clone(), - is_mouse_over, - ) } fn hash_layout(&self, state: &mut Hasher) { @@ -373,38 +363,9 @@ impl State { } } -/// The renderer of an [`Viewer`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Viewer`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// Draws the [`Viewer`]. - /// - /// It receives: - /// - the [`State`] of the [`Viewer`] - /// - the bounds of the [`Viewer`] widget - /// - the [`Size`] of the scaled [`Viewer`] image - /// - the translation of the clipped image - /// - the [`Handle`] to the underlying image - /// - whether the mouse is over the [`Viewer`] or not - /// - /// [`Handle`]: image::Handle - fn draw( - &mut self, - state: &State, - bounds: Rectangle, - image_size: Size, - translation: Vector, - handle: image::Handle, - is_mouse_over: bool, - ) -> Self::Output; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + image::Renderer, + Renderer: 'a + image::Renderer, Message: 'a, { fn from(viewer: Viewer<'a>) -> Element<'a, Message, Renderer> { diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 26a72409..b4a8cdb1 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -32,7 +32,6 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; -use crate::row; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, @@ -480,66 +479,56 @@ where layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, - ) -> Renderer::Output { - let picked_split = self - .state - .picked_split() - .and_then(|(split, axis)| { - let bounds = layout.bounds(); - - let splits = self - .state - .split_regions(f32::from(self.spacing), bounds.size()); - - let (_axis, region, ratio) = splits.get(&split)?; - - let region = axis.split_line_bounds( - *region, - *ratio, - f32::from(self.spacing), - ); - - Some((axis, region + Vector::new(bounds.x, bounds.y), true)) - }) - .or_else(|| match self.on_resize { - Some((leeway, _)) => { - let bounds = layout.bounds(); - - let relative_cursor = Point::new( - cursor_position.x - bounds.x, - cursor_position.y - bounds.y, - ); - - let splits = self - .state - .split_regions(f32::from(self.spacing), bounds.size()); - - let (_split, axis, region) = hovered_split( - splits.iter(), - f32::from(self.spacing + leeway), - relative_cursor, - )?; - - Some(( - axis, - region + Vector::new(bounds.x, bounds.y), - false, - )) - } - None => None, - }); - - self::Renderer::draw( - renderer, - defaults, - &self.elements, - self.state.picked_pane(), - picked_split, - layout, - &self.style, - cursor_position, - viewport, - ) + ) { + // let picked_split = self + // .state + // .picked_split() + // .and_then(|(split, axis)| { + // let bounds = layout.bounds(); + + // let splits = self + // .state + // .split_regions(f32::from(self.spacing), bounds.size()); + + // let (_axis, region, ratio) = splits.get(&split)?; + + // let region = axis.split_line_bounds( + // *region, + // *ratio, + // f32::from(self.spacing), + // ); + + // Some((axis, region + Vector::new(bounds.x, bounds.y), true)) + // }) + // .or_else(|| match self.on_resize { + // Some((leeway, _)) => { + // let bounds = layout.bounds(); + + // let relative_cursor = Point::new( + // cursor_position.x - bounds.x, + // cursor_position.y - bounds.y, + // ); + + // let splits = self + // .state + // .split_regions(f32::from(self.spacing), bounds.size()); + + // let (_split, axis, region) = hovered_split( + // splits.iter(), + // f32::from(self.spacing + leeway), + // relative_cursor, + // )?; + + // Some(( + // axis, + // region + Vector::new(bounds.x, bounds.y), + // false, + // )) + // } + // None => None, + // }); + + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -578,69 +567,12 @@ where pub trait Renderer: crate::Renderer + container::Renderer + Sized { /// The style supported by this renderer. type Style: Default; - - /// Draws a [`PaneGrid`]. - /// - /// It receives: - /// - the elements of the [`PaneGrid`] - /// - the [`Pane`] that is currently being dragged - /// - the [`Axis`] that is currently being resized - /// - the [`Layout`] of the [`PaneGrid`] and its elements - /// - the cursor position - fn draw( - &mut self, - defaults: &Self::Defaults, - content: &[(Pane, Content<'_, Message, Self>)], - dragging: Option<(Pane, Point)>, - resizing: Option<(Axis, Rectangle, bool)>, - layout: Layout<'_>, - style: &::Style, - cursor_position: Point, - viewport: &Rectangle, - ) -> Self::Output; - - /// Draws a [`Pane`]. - /// - /// It receives: - /// - the [`TitleBar`] of the [`Pane`], if any - /// - the [`Content`] of the [`Pane`] - /// - the [`Layout`] of the [`Pane`] and its elements - /// - the cursor position - fn draw_pane( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - style: &::Style, - title_bar: Option<(&TitleBar<'_, Message, Self>, Layout<'_>)>, - body: (&Element<'_, Message, Self>, Layout<'_>), - cursor_position: Point, - viewport: &Rectangle, - ) -> Self::Output; - - /// Draws a [`TitleBar`]. - /// - /// It receives: - /// - the bounds, style of the [`TitleBar`] - /// - the style of the [`TitleBar`] - /// - the content of the [`TitleBar`] with its layout - /// - the controls of the [`TitleBar`] with their [`Layout`], if any - /// - the cursor position - fn draw_title_bar( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - style: &::Style, - content: (&Element<'_, Message, Self>, Layout<'_>), - controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>, - cursor_position: Point, - viewport: &Rectangle, - ) -> Self::Output; } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + row::Renderer, + Renderer: 'a + self::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index bac9fdd4..e94955f7 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -61,32 +61,33 @@ where layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, - ) -> Renderer::Output { - if let Some(title_bar) = &self.title_bar { - let mut children = layout.children(); - let title_bar_layout = children.next().unwrap(); - let body_layout = children.next().unwrap(); - - renderer.draw_pane( - defaults, - layout.bounds(), - &self.style, - Some((title_bar, title_bar_layout)), - (&self.body, body_layout), - cursor_position, - viewport, - ) - } else { - renderer.draw_pane( - defaults, - layout.bounds(), - &self.style, - None, - (&self.body, layout), - cursor_position, - viewport, - ) - } + ) { + // TODO + // if let Some(title_bar) = &self.title_bar { + // let mut children = layout.children(); + // let title_bar_layout = children.next().unwrap(); + // let body_layout = children.next().unwrap(); + + // renderer.draw_pane( + // defaults, + // layout.bounds(), + // &self.style, + // Some((title_bar, title_bar_layout)), + // (&self.body, body_layout), + // cursor_position, + // viewport, + // ) + // } else { + // renderer.draw_pane( + // defaults, + // layout.bounds(), + // &self.style, + // None, + // (&self.body, layout), + // cursor_position, + // viewport, + // ) + // } } /// Returns whether the [`Content`] with the given [`Layout`] can be picked diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 070010f8..9b0b7c78 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -90,34 +90,34 @@ where cursor_position: Point, viewport: &Rectangle, show_controls: bool, - ) -> Renderer::Output { - let mut children = layout.children(); - let padded = children.next().unwrap(); - - let mut children = padded.children(); - let title_layout = children.next().unwrap(); - - let controls = if let Some(controls) = &self.controls { - let controls_layout = children.next().unwrap(); - - if show_controls || self.always_show_controls { - Some((controls, controls_layout)) - } else { - None - } - } else { - None - }; - - renderer.draw_title_bar( - defaults, - layout.bounds(), - &self.style, - (&self.content, title_layout), - controls, - cursor_position, - viewport, - ) + ) { + // let mut children = layout.children(); + // let padded = children.next().unwrap(); + + // let mut children = padded.children(); + // let title_layout = children.next().unwrap(); + + // let controls = if let Some(controls) = &self.controls { + // let controls_layout = children.next().unwrap(); + + // if show_controls || self.always_show_controls { + // Some((controls, controls_layout)) + // } else { + // None + // } + // } else { + // None + // }; + + // renderer.draw_title_bar( + // defaults, + // layout.bounds(), + // &self.style, + // (&self.content, title_layout), + // controls, + // cursor_position, + // viewport, + // ) } /// Returns whether the mouse cursor is over the pick area of the diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index d7792000..7154a572 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -327,18 +327,8 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - self::Renderer::draw( - renderer, - layout.bounds(), - cursor_position, - self.selected.as_ref().map(ToString::to_string), - self.placeholder.as_ref().map(String::as_str), - self.padding, - self.text_size.unwrap_or(renderer.default_size()), - self.font, - &self.style, - ) + ) { + // TODO } fn overlay( @@ -387,19 +377,6 @@ pub trait Renderer: text::Renderer + menu::Renderer { fn menu_style( style: &::Style, ) -> ::Style; - - /// Draws a [`PickList`]. - fn draw( - &mut self, - bounds: Rectangle, - cursor_position: Point, - selected: Option, - placeholder: Option<&str>, - padding: Padding, - text_size: u16, - font: Self::Font, - style: &::Style, - ) -> Self::Output; } impl<'a, T: 'a, Message, Renderer> Into> diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index d294f198..d8cf5376 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -97,13 +97,8 @@ where layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - layout.bounds(), - self.range.clone(), - self.value, - &self.style, - ) + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -127,22 +122,6 @@ pub trait Renderer: crate::Renderer { /// The default height of a [`ProgressBar`]. const DEFAULT_HEIGHT: u16; - - /// Draws a [`ProgressBar`]. - /// - /// It receives: - /// * the bounds of the [`ProgressBar`] - /// * the range of values of the [`ProgressBar`] - /// * the current value of the [`ProgressBar`] - /// * maybe a specific background of the [`ProgressBar`] - /// * maybe a specific active color of the [`ProgressBar`] - fn draw( - &self, - bounds: Rectangle, - range: RangeInclusive, - value: f32, - style: &Self::Style, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 513b2fce..c6955079 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -5,7 +5,6 @@ use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; use crate::mouse; -use crate::row; use crate::text; use crate::touch; use crate::{ @@ -136,7 +135,7 @@ where impl Widget for Radio where Message: Clone, - Renderer: self::Renderer + text::Renderer + row::Renderer, + Renderer: self::Renderer + text::Renderer, { fn width(&self) -> Length { self.width @@ -199,36 +198,37 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - let bounds = layout.bounds(); - let mut children = layout.children(); + ) { + // TODO + // let bounds = layout.bounds(); + // let mut children = layout.children(); - let radio_layout = children.next().unwrap(); - let label_layout = children.next().unwrap(); - let radio_bounds = radio_layout.bounds(); + // let radio_layout = children.next().unwrap(); + // let label_layout = children.next().unwrap(); + // let radio_bounds = radio_layout.bounds(); - let label = text::Renderer::draw( - renderer, - defaults, - label_layout.bounds(), - &self.label, - self.text_size.unwrap_or(renderer.default_size()), - self.font, - self.text_color, - alignment::Horizontal::Left, - alignment::Vertical::Center, - ); + // let label = text::Renderer::draw( + // renderer, + // defaults, + // label_layout.bounds(), + // &self.label, + // self.text_size.unwrap_or(renderer.default_size()), + // self.font, + // self.text_color, + // alignment::Horizontal::Left, + // alignment::Vertical::Center, + // ); - let is_mouse_over = bounds.contains(cursor_position); + // let is_mouse_over = bounds.contains(cursor_position); - self::Renderer::draw( - renderer, - radio_bounds, - self.is_selected, - is_mouse_over, - label, - &self.style, - ) + // self::Renderer::draw( + // renderer, + // radio_bounds, + // self.is_selected, + // is_mouse_over, + // label, + // &self.style, + // ) } fn hash_layout(&self, state: &mut Hasher) { @@ -254,29 +254,13 @@ pub trait Renderer: crate::Renderer { /// The default spacing of a [`Radio`] button. const DEFAULT_SPACING: u16; - - /// Draws a [`Radio`] button. - /// - /// It receives: - /// * the bounds of the [`Radio`] - /// * whether the [`Radio`] is selected or not - /// * whether the mouse is over the [`Radio`] or not - /// * the drawn label of the [`Radio`] - fn draw( - &mut self, - bounds: Rectangle, - is_selected: bool, - is_mouse_over: bool, - label: Self::Output, - style: &Self::Style, - ) -> Self::Output; } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + self::Renderer + row::Renderer + text::Renderer, + Renderer: 'a + self::Renderer + text::Renderer, { fn from(radio: Radio) -> Element<'a, Message, Renderer> { Element::new(radio) diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 1923f213..04a1f864 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -104,7 +104,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget for Row<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -168,14 +168,15 @@ where layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - defaults, - &self.children, - layout, - cursor_position, - viewport, - ) + ) { + // TODO + // renderer.draw( + // defaults, + // &self.children, + // layout, + // cursor_position, + // viewport, + // ) } fn hash_layout(&self, state: &mut Hasher) { @@ -207,33 +208,10 @@ where } } -/// The renderer of a [`Row`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Row`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// Draws a [`Row`]. - /// - /// It receives: - /// - the children of the [`Row`] - /// - the [`Layout`] of the [`Row`] and its children - /// - the cursor position - fn draw( - &mut self, - defaults: &Self::Defaults, - children: &[Element<'_, Message, Self>], - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - ) -> Self::Output; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { fn from(row: Row<'a, Message, Renderer>) -> Element<'a, Message, Renderer> { diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 18c88658..1fab77bc 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -72,8 +72,9 @@ where layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw(layout.bounds(), &self.style, self.is_horizontal) + ) { + // TODO + // renderer.draw(layout.bounds(), &self.style, self.is_horizontal) } fn hash_layout(&self, state: &mut Hasher) { @@ -89,19 +90,6 @@ where pub trait Renderer: crate::Renderer { /// The style supported by this renderer. type Style: Default; - - /// Draws a [`Rule`]. - /// - /// It receives: - /// * the bounds of the [`Rule`] - /// * the style of the [`Rule`] - /// * whether the [`Rule`] is horizontal (true) or vertical (false) - fn draw( - &mut self, - bounds: Rectangle, - style: &Self::Style, - is_horizontal: bool, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index a8e467d3..1c897dc5 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -1,5 +1,4 @@ //! Navigate an endless amount of content with a scrollbar. -use crate::column; use crate::event::{self, Event}; use crate::layout; use crate::mouse; @@ -381,57 +380,45 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - let bounds = layout.bounds(); - let content_layout = layout.children().next().unwrap(); - let content_bounds = content_layout.bounds(); - let offset = self.state.offset(bounds, content_bounds); - let scrollbar = renderer.scrollbar( - bounds, - content_bounds, - offset, - self.scrollbar_width, - self.scrollbar_margin, - self.scroller_width, - ); - - let is_mouse_over = bounds.contains(cursor_position); - let is_mouse_over_scrollbar = scrollbar - .as_ref() - .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) - .unwrap_or(false); - - let content = { - let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { - Point::new(cursor_position.x, cursor_position.y + offset as f32) - } else { - Point::new(cursor_position.x, -1.0) - }; - - self.content.draw( - renderer, - defaults, - content_layout, - cursor_position, - &Rectangle { - y: bounds.y + offset as f32, - ..bounds - }, - ) - }; - - self::Renderer::draw( - renderer, - &self.state, - bounds, - content_layout.bounds(), - is_mouse_over, - is_mouse_over_scrollbar, - scrollbar, - offset, - &self.style, - content, - ) + ) { + // TODO + // let bounds = layout.bounds(); + // let content_layout = layout.children().next().unwrap(); + // let content_bounds = content_layout.bounds(); + // let offset = self.state.offset(bounds, content_bounds); + // let scrollbar = renderer.scrollbar( + // bounds, + // content_bounds, + // offset, + // self.scrollbar_width, + // self.scrollbar_margin, + // self.scroller_width, + // ); + + // let is_mouse_over = bounds.contains(cursor_position); + // let is_mouse_over_scrollbar = scrollbar + // .as_ref() + // .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + // .unwrap_or(false); + + // let content = { + // let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { + // Point::new(cursor_position.x, cursor_position.y + offset as f32) + // } else { + // Point::new(cursor_position.x, -1.0) + // }; + + // self.content.draw( + // renderer, + // defaults, + // content_layout, + // cursor_position, + // &Rectangle { + // y: bounds.y + offset as f32, + // ..bounds + // }, + // ) + // }; } fn hash_layout(&self, state: &mut Hasher) { @@ -635,7 +622,7 @@ pub struct Scroller { /// able to use a [`Scrollable`] in your user interface. /// /// [renderer]: crate::renderer -pub trait Renderer: column::Renderer + Sized { +pub trait Renderer: crate::Renderer + Sized { /// The style supported by this renderer. type Style: Default; @@ -650,30 +637,6 @@ pub trait Renderer: column::Renderer + Sized { scrollbar_margin: u16, scroller_width: u16, ) -> Option; - - /// Draws the [`Scrollable`]. - /// - /// It receives: - /// - the [`State`] of the [`Scrollable`] - /// - the bounds of the [`Scrollable`] widget - /// - the bounds of the [`Scrollable`] content - /// - whether the mouse is over the [`Scrollable`] or not - /// - whether the mouse is over the [`Scrollbar`] or not - /// - a optional [`Scrollbar`] to be rendered - /// - the scrolling offset - /// - the drawn content - fn draw( - &mut self, - scrollable: &State, - bounds: Rectangle, - content_bounds: Rectangle, - is_mouse_over: bool, - is_mouse_over_scrollbar: bool, - scrollbar: Option, - offset: u32, - style: &Self::Style, - content: Self::Output, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 2a74d5a3..bcf811fe 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -250,18 +250,19 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - let start = *self.range.start(); - let end = *self.range.end(); - - renderer.draw( - layout.bounds(), - cursor_position, - start.into() as f32..=end.into() as f32, - self.value.into() as f32, - self.state.is_dragging, - &self.style, - ) + ) { + // TODO + // let start = *self.range.start(); + // let end = *self.range.end(); + + // renderer.draw( + // layout.bounds(), + // cursor_position, + // start.into() as f32..=end.into() as f32, + // self.value.into() as f32, + // self.state.is_dragging, + // &self.style, + // ) } fn hash_layout(&self, state: &mut Hasher) { @@ -284,24 +285,6 @@ pub trait Renderer: crate::Renderer { /// The default height of a [`Slider`]. const DEFAULT_HEIGHT: u16; - - /// Draws a [`Slider`]. - /// - /// It receives: - /// * the current cursor position - /// * the bounds of the [`Slider`] - /// * the local state of the [`Slider`] - /// * the range of values of the [`Slider`] - /// * the current value of the [`Slider`] - fn draw( - &mut self, - bounds: Rectangle, - cursor_position: Point, - range: RangeInclusive, - value: f32, - is_dragging: bool, - style: &Self::Style, - ) -> Self::Output; } impl<'a, T, Message, Renderer> From> diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index 6b34ece8..9a70dab1 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -39,7 +39,7 @@ impl Space { impl Widget for Space where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -66,8 +66,7 @@ where layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw(layout.bounds()) + ) { } fn hash_layout(&self, state: &mut Hasher) { @@ -78,17 +77,9 @@ where } } -/// The renderer of an amount of [`Space`]. -pub trait Renderer: crate::Renderer { - /// Draws an amount of empty [`Space`]. - /// - /// You should most likely return an empty primitive here. - fn draw(&mut self, bounds: Rectangle) -> Self::Output; -} - impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, Message: 'a, { fn from(space: Space) -> Element<'a, Message, Renderer> { diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 9cd61918..737dd8d4 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -94,8 +94,9 @@ where layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw(self.handle.clone(), layout) + ) { + // TODO + // renderer.draw(self.handle.clone(), layout) } fn hash_layout(&self, state: &mut Hasher) { @@ -187,9 +188,6 @@ impl std::fmt::Debug for Data { pub trait Renderer: crate::Renderer { /// Returns the default dimensions of an [`Svg`] for the given [`Handle`]. fn dimensions(&self, handle: &Handle) -> (u32, u32); - - /// Draws an [`Svg`]. - fn draw(&mut self, handle: Handle, layout: Layout<'_>) -> Self::Output; } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 168d49c2..9915a6e9 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -133,22 +133,13 @@ where fn draw( &self, - renderer: &mut Renderer, - defaults: &Renderer::Defaults, - layout: Layout<'_>, + _renderer: &mut Renderer, + _defaults: &Renderer::Defaults, + _layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw( - defaults, - layout.bounds(), - &self.content, - self.size.unwrap_or(renderer.default_size()), - self.font, - self.color, - self.horizontal_alignment, - self.vertical_alignment, - ) + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -201,27 +192,6 @@ pub trait Renderer: crate::Renderer { point: Point, nearest_only: bool, ) -> Option; - - /// Draws a [`Text`] fragment. - /// - /// It receives: - /// * the bounds of the [`Text`] - /// * the contents of the [`Text`] - /// * the size of the [`Text`] - /// * the color of the [`Text`] - /// * the [`HorizontalAlignment`] of the [`Text`] - /// * the [`VerticalAlignment`] of the [`Text`] - fn draw( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - content: &str, - size: u16, - font: Self::Font, - color: Option, - horizontal_alignment: alignment::Horizontal, - vertical_alignment: alignment::Vertical, - ) -> Self::Output; } impl<'a, Message, Renderer> From> diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 84d171be..fe95eb95 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -170,38 +170,39 @@ where layout: Layout<'_>, cursor_position: Point, value: Option<&Value>, - ) -> Renderer::Output { - let value = value.unwrap_or(&self.value); - let bounds = layout.bounds(); - let text_bounds = layout.children().next().unwrap().bounds(); - - if self.is_secure { - self::Renderer::draw( - renderer, - bounds, - text_bounds, - cursor_position, - self.font, - self.size.unwrap_or(renderer.default_size()), - &self.placeholder, - &value.secure(), - &self.state, - &self.style, - ) - } else { - self::Renderer::draw( - renderer, - bounds, - text_bounds, - cursor_position, - self.font, - self.size.unwrap_or(renderer.default_size()), - &self.placeholder, - value, - &self.state, - &self.style, - ) - } + ) { + // TODO + // let value = value.unwrap_or(&self.value); + // let bounds = layout.bounds(); + // let text_bounds = layout.children().next().unwrap().bounds(); + + // if self.is_secure { + // self::Renderer::draw( + // renderer, + // bounds, + // text_bounds, + // cursor_position, + // self.font, + // self.size.unwrap_or(renderer.default_size()), + // &self.placeholder, + // &value.secure(), + // &self.state, + // &self.style, + // ) + // } else { + // self::Renderer::draw( + // renderer, + // bounds, + // text_bounds, + // cursor_position, + // self.font, + // self.size.unwrap_or(renderer.default_size()), + // &self.placeholder, + // value, + // &self.state, + // &self.style, + // ) + // } } } @@ -630,7 +631,7 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { + ) { self.draw(renderer, layout, cursor_position, None) } @@ -673,28 +674,6 @@ pub trait Renderer: text::Renderer + Sized { state: &State, ) -> f32; - /// Draws a [`TextInput`]. - /// - /// It receives: - /// - the bounds of the [`TextInput`] - /// - the bounds of the text (i.e. the current value) - /// - the cursor position - /// - the placeholder to show when the value is empty - /// - the current [`Value`] - /// - the current [`State`] - fn draw( - &mut self, - bounds: Rectangle, - text_bounds: Rectangle, - cursor_position: Point, - font: Self::Font, - size: u16, - placeholder: &str, - value: &Value, - state: &State, - style: &Self::Style, - ) -> Self::Output; - /// Computes the position of the text cursor at the given X coordinate of /// a [`TextInput`]. fn find_cursor_position( diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index c624be4c..4a1f1f5d 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -5,7 +5,6 @@ use crate::alignment; use crate::event; use crate::layout; use crate::mouse; -use crate::row; use crate::text; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, @@ -119,7 +118,7 @@ impl impl Widget for Toggler where - Renderer: self::Renderer + text::Renderer + row::Renderer, + Renderer: self::Renderer + text::Renderer, { fn width(&self) -> Length { self.width @@ -190,43 +189,35 @@ where layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - let bounds = layout.bounds(); - let mut children = layout.children(); - - let label = match &self.label { - Some(label) => { - let label_layout = children.next().unwrap(); - - Some(text::Renderer::draw( - renderer, - defaults, - label_layout.bounds(), - &label, - self.text_size.unwrap_or(renderer.default_size()), - self.font, - None, - self.text_alignment, - alignment::Vertical::Center, - )) - } - - None => None, - }; - - let toggler_layout = children.next().unwrap(); - let toggler_bounds = toggler_layout.bounds(); - - let is_mouse_over = bounds.contains(cursor_position); - - self::Renderer::draw( - renderer, - toggler_bounds, - self.is_active, - is_mouse_over, - label, - &self.style, - ) + ) { + // TODO + // let bounds = layout.bounds(); + // let mut children = layout.children(); + + // let label = match &self.label { + // Some(label) => { + // let label_layout = children.next().unwrap(); + + // Some(text::Renderer::draw( + // renderer, + // defaults, + // label_layout.bounds(), + // &label, + // self.text_size.unwrap_or(renderer.default_size()), + // self.font, + // None, + // self.text_alignment, + // alignment::Vertical::Center, + // )) + // } + + // None => None, + // }; + + // let toggler_layout = children.next().unwrap(); + // let toggler_bounds = toggler_layout.bounds(); + + // let is_mouse_over = bounds.contains(cursor_position); } fn hash_layout(&self, state: &mut Hasher) { @@ -249,29 +240,12 @@ pub trait Renderer: crate::Renderer { /// The default size of a [`Toggler`]. const DEFAULT_SIZE: u16; - - /// Draws a [`Toggler`]. - /// - /// It receives: - /// * the bounds of the [`Toggler`] - /// * whether the [`Toggler`] is activated or not - /// * whether the mouse is over the [`Toggler`] or not - /// * the drawn label of the [`Toggler`] - /// * the style of the [`Toggler`] - fn draw( - &mut self, - bounds: Rectangle, - is_active: bool, - is_mouse_over: bool, - label: Option, - style: &Self::Style, - ) -> Self::Output; } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + text::Renderer + row::Renderer, + Renderer: 'a + self::Renderer + text::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 276afd41..83d04675 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -136,25 +136,13 @@ where fn draw( &self, - renderer: &mut Renderer, - defaults: &Renderer::Defaults, - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - ) -> Renderer::Output { - self::Renderer::draw( - renderer, - defaults, - cursor_position, - layout, - viewport, - &self.content, - &self.tooltip, - self.position, - &self.style, - self.gap, - self.padding, - ) + _renderer: &mut Renderer, + _defaults: &Renderer::Defaults, + _layout: Layout<'_>, + _cursor_position: Point, + _viewport: &Rectangle, + ) { + // TODO } fn hash_layout(&self, state: &mut Hasher) { @@ -177,23 +165,6 @@ pub trait Renderer: { /// The default padding of a [`Tooltip`] drawn by this renderer. const DEFAULT_PADDING: u16; - - /// Draws a [`Tooltip`]. - /// - /// [`Tooltip`]: struct.Tooltip.html - fn draw( - &mut self, - defaults: &Self::Defaults, - cursor_position: Point, - content_layout: Layout<'_>, - viewport: &Rectangle, - content: &Element<'_, Message, Self>, - tooltip: &Text, - position: Position, - style: &::Style, - gap: u16, - padding: u16, - ) -> Self::Output; } impl<'a, Message, Renderer> From> -- cgit From 3a0c503db99eb3d45ac971132904df419ee566b6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 16:59:19 +0700 Subject: Implement `Widget::draw` for `Text` --- native/src/widget/text.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 9915a6e9..ea1ba7ac 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -1,6 +1,7 @@ //! Write some text for your users to read. use crate::alignment; use crate::layout; +use crate::renderer; use crate::{ Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, }; @@ -133,13 +134,35 @@ where fn draw( &self, - _renderer: &mut Renderer, + renderer: &mut Renderer, _defaults: &Renderer::Defaults, - _layout: Layout<'_>, + layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { - // TODO + let bounds = layout.bounds(); + + let x = match self.horizontal_alignment { + alignment::Horizontal::Left => bounds.x, + alignment::Horizontal::Center => bounds.center_x(), + alignment::Horizontal::Right => bounds.x + bounds.width, + }; + + let y = match self.vertical_alignment { + alignment::Vertical::Top => bounds.y, + alignment::Vertical::Center => bounds.center_y(), + alignment::Vertical::Bottom => bounds.y + bounds.height, + }; + + renderer.fill_text(renderer::text::Section { + content: &self.content, + size: self.size.map(f32::from), + bounds: Rectangle { x, y, ..bounds }, + color: self.color, + font: self.font, + horizontal_alignment: self.horizontal_alignment, + vertical_alignment: self.vertical_alignment, + }); } fn hash_layout(&self, state: &mut Hasher) { @@ -159,10 +182,7 @@ where /// able to use [`Text`] in your user interface. /// /// [renderer]: crate::Renderer -pub trait Renderer: crate::Renderer { - /// The font type used for [`Text`]. - type Font: Default + Copy; - +pub trait Renderer: renderer::Text { /// Returns the default size of [`Text`]. fn default_size(&self) -> u16; -- cgit From 1ab2afe72d377d8fa9a5b2d71cc23f3a729351a4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 17:05:08 +0700 Subject: Implement `Widget::draw` for `Column` --- native/src/widget/column.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 61b2361f..7cf6d345 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -170,7 +170,9 @@ where cursor_position: Point, viewport: &Rectangle, ) { - // TODO + for (child, layout) in self.children.iter().zip(layout.children()) { + child.draw(renderer, defaults, layout, cursor_position, viewport); + } } fn hash_layout(&self, state: &mut Hasher) { -- cgit From f8895a42b05b93f28416597c8115f7b598885ddb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 17:05:37 +0700 Subject: Implement `Widget::draw` for `Row` --- native/src/widget/row.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 04a1f864..7eb5ab55 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -169,14 +169,9 @@ where cursor_position: Point, viewport: &Rectangle, ) { - // TODO - // renderer.draw( - // defaults, - // &self.children, - // layout, - // cursor_position, - // viewport, - // ) + for (child, layout) in self.children.iter().zip(layout.children()) { + child.draw(renderer, defaults, layout, cursor_position, viewport); + } } fn hash_layout(&self, state: &mut Hasher) { -- cgit From 7c4738735b6cd5eafb544de01dbf5dd5091dc188 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 17:05:47 +0700 Subject: Implement `Widget::draw` for `Container` --- native/src/widget/container.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index f43de2a5..af40f2ab 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -180,7 +180,13 @@ where cursor_position: Point, viewport: &Rectangle, ) { - // TODO + self.content.draw( + renderer, + defaults, + layout.children().next().unwrap(), + cursor_position, + viewport, + ); } fn hash_layout(&self, state: &mut Hasher) { -- cgit From dfceee99aad9462f09ca61081e68e1decb2fed92 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Oct 2021 17:15:29 +0700 Subject: Implement `Widget::draw` for `Scrollable` Rendering the scroller is still WIP --- native/src/widget/scrollable.rs | 126 ++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 38 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 1c897dc5..ba3d3dd6 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -381,44 +381,94 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // let bounds = layout.bounds(); - // let content_layout = layout.children().next().unwrap(); - // let content_bounds = content_layout.bounds(); - // let offset = self.state.offset(bounds, content_bounds); - // let scrollbar = renderer.scrollbar( - // bounds, - // content_bounds, - // offset, - // self.scrollbar_width, - // self.scrollbar_margin, - // self.scroller_width, - // ); - - // let is_mouse_over = bounds.contains(cursor_position); - // let is_mouse_over_scrollbar = scrollbar - // .as_ref() - // .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) - // .unwrap_or(false); - - // let content = { - // let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { - // Point::new(cursor_position.x, cursor_position.y + offset as f32) - // } else { - // Point::new(cursor_position.x, -1.0) - // }; - - // self.content.draw( - // renderer, - // defaults, - // content_layout, - // cursor_position, - // &Rectangle { - // y: bounds.y + offset as f32, - // ..bounds - // }, - // ) - // }; + let bounds = layout.bounds(); + let content_layout = layout.children().next().unwrap(); + let content_bounds = content_layout.bounds(); + let offset = self.state.offset(bounds, content_bounds); + let scrollbar = renderer.scrollbar( + bounds, + content_bounds, + offset, + self.scrollbar_width, + self.scrollbar_margin, + self.scroller_width, + ); + + let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over_scrollbar = scrollbar + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false); + + let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { + Point::new(cursor_position.x, cursor_position.y + offset as f32) + } else { + Point::new(cursor_position.x, -1.0) + }; + + if let Some(scrollbar) = scrollbar { + renderer.with_layer(bounds, Vector::new(0, offset), |renderer| { + self.content.draw( + renderer, + defaults, + content_layout, + cursor_position, + &Rectangle { + y: bounds.y + offset as f32, + ..bounds + }, + ); + }); + + // TODO: Draw scroller + // let style = if self.state.is_scroller_grabbed() { + // style_sheet.dragging() + // } else if is_mouse_over_scrollbar { + // style_sheet.hovered() + // } else { + // style_sheet.active() + // }; + + // let is_scrollbar_visible = + // style.background.is_some() || style.border_width > 0.0; + + // if is_mouse_over + // || self.state.is_scroller_grabbed() + // || is_scrollbar_visible + // { + // // Primitive::Quad { + // // bounds: scrollbar.scroller.bounds, + // // background: Background::Color(style.scroller.color), + // // border_radius: style.scroller.border_radius, + // // border_width: style.scroller.border_width, + // // border_color: style.scroller.border_color, + // // } + // }; + + // TODO: Draw scrollbar + // if is_scrollbar_visible { + // Primitive::Quad { + // bounds: scrollbar.bounds, + // background: style + // .background + // .unwrap_or(Background::Color(Color::TRANSPARENT)), + // border_radius: style.border_radius, + // border_width: style.border_width, + // border_color: style.border_color, + // } + //} + } else { + self.content.draw( + renderer, + defaults, + content_layout, + cursor_position, + &Rectangle { + y: bounds.y + offset as f32, + ..bounds + }, + ); + } } fn hash_layout(&self, state: &mut Hasher) { -- cgit From 54a9a232f8110364972a8eef966b7b7477573f4f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 14:48:33 +0700 Subject: Draw scrollbar in `Widget::draw` for `Scrollable` --- native/src/widget/pick_list.rs | 3 +- native/src/widget/scrollable.rs | 207 ++++++++++++++++++++++------------------ 2 files changed, 114 insertions(+), 96 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 7154a572..73b01b01 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -5,7 +5,6 @@ use crate::layout; use crate::mouse; use crate::overlay; use crate::overlay::menu::{self, Menu}; -use crate::scrollable; use crate::text; use crate::touch; use crate::{ @@ -145,7 +144,7 @@ where T: Clone + ToString + Eq, [T]: ToOwned>, Message: 'static, - Renderer: self::Renderer + scrollable::Renderer + 'a, + Renderer: self::Renderer + 'a, { fn width(&self) -> Length { self.width diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index ba3d3dd6..98357928 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -3,18 +3,21 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; +use crate::renderer; use crate::touch; use crate::{ - Alignment, Clipboard, Column, Element, Hasher, Layout, Length, Padding, - Point, Rectangle, Size, Vector, Widget, + Alignment, Background, Clipboard, Color, Column, Element, Hasher, Layout, + Length, Padding, Point, Rectangle, Size, Vector, Widget, }; use std::{f32, hash::Hash, u32}; +pub use iced_style::scrollable::StyleSheet; + /// A widget that can vertically display an infinite amount of content with a /// scrollbar. #[allow(missing_debug_implementations)] -pub struct Scrollable<'a, Message, Renderer: self::Renderer> { +pub struct Scrollable<'a, Message, Renderer> { state: &'a mut State, height: Length, max_height: u32, @@ -23,10 +26,10 @@ pub struct Scrollable<'a, Message, Renderer: self::Renderer> { scroller_width: u16, content: Column<'a, Message, Renderer>, on_scroll: Option Message>>, - style: Renderer::Style, + style_sheet: &'a dyn StyleSheet, } -impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { +impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> { /// Creates a new [`Scrollable`] with the given [`State`]. pub fn new(state: &'a mut State) -> Self { Scrollable { @@ -38,7 +41,7 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { scroller_width: 10, content: Column::new(), on_scroll: None, - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -119,8 +122,11 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { } /// Sets the style of the [`Scrollable`] . - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style<'b>(mut self, style_sheet: &'b dyn StyleSheet) -> Self + where + 'b: 'a, + { + self.style_sheet = style_sheet; self } @@ -150,12 +156,63 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { )); } } + + fn scrollbar( + &self, + bounds: Rectangle, + content_bounds: Rectangle, + ) -> Option { + let offset = self.state.offset(bounds, content_bounds); + + if content_bounds.height > bounds.height { + let outer_width = self.scrollbar_width.max(self.scroller_width) + + 2 * self.scrollbar_margin; + + let outer_bounds = Rectangle { + x: bounds.x + bounds.width - outer_width as f32, + y: bounds.y, + width: outer_width as f32, + height: bounds.height, + }; + + let scrollbar_bounds = Rectangle { + x: bounds.x + bounds.width + - f32::from(outer_width / 2 + self.scrollbar_width / 2), + y: bounds.y, + width: self.scrollbar_width as f32, + height: bounds.height, + }; + + let ratio = bounds.height / content_bounds.height; + let scroller_height = bounds.height * ratio; + let y_offset = offset as f32 * ratio; + + let scroller_bounds = Rectangle { + x: bounds.x + bounds.width + - f32::from(outer_width / 2 + self.scroller_width / 2), + y: scrollbar_bounds.y + y_offset, + width: self.scroller_width as f32, + height: scroller_height, + }; + + Some(Scrollbar { + outer_bounds, + bounds: scrollbar_bounds, + margin: self.scrollbar_margin, + scroller: Scroller { + bounds: scroller_bounds, + }, + }) + } else { + None + } + } } impl<'a, Message, Renderer> Widget for Scrollable<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { Widget::::width(&self.content) @@ -201,15 +258,7 @@ where let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); - let offset = self.state.offset(bounds, content_bounds); - let scrollbar = renderer.scrollbar( - bounds, - content_bounds, - offset, - self.scrollbar_width, - self.scrollbar_margin, - self.scroller_width, - ); + let scrollbar = self.scrollbar(bounds, content_bounds); let is_mouse_over_scrollbar = scrollbar .as_ref() .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) @@ -385,14 +434,7 @@ where let content_layout = layout.children().next().unwrap(); let content_bounds = content_layout.bounds(); let offset = self.state.offset(bounds, content_bounds); - let scrollbar = renderer.scrollbar( - bounds, - content_bounds, - offset, - self.scrollbar_width, - self.scrollbar_margin, - self.scroller_width, - ); + let scrollbar = self.scrollbar(bounds, content_bounds); let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over_scrollbar = scrollbar @@ -420,43 +462,43 @@ where ); }); - // TODO: Draw scroller - // let style = if self.state.is_scroller_grabbed() { - // style_sheet.dragging() - // } else if is_mouse_over_scrollbar { - // style_sheet.hovered() - // } else { - // style_sheet.active() - // }; - - // let is_scrollbar_visible = - // style.background.is_some() || style.border_width > 0.0; - - // if is_mouse_over - // || self.state.is_scroller_grabbed() - // || is_scrollbar_visible - // { - // // Primitive::Quad { - // // bounds: scrollbar.scroller.bounds, - // // background: Background::Color(style.scroller.color), - // // border_radius: style.scroller.border_radius, - // // border_width: style.scroller.border_width, - // // border_color: style.scroller.border_color, - // // } - // }; - - // TODO: Draw scrollbar - // if is_scrollbar_visible { - // Primitive::Quad { - // bounds: scrollbar.bounds, - // background: style - // .background - // .unwrap_or(Background::Color(Color::TRANSPARENT)), - // border_radius: style.border_radius, - // border_width: style.border_width, - // border_color: style.border_color, - // } - //} + let style = if self.state.is_scroller_grabbed() { + self.style_sheet.dragging() + } else if is_mouse_over_scrollbar { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + let is_scrollbar_visible = + style.background.is_some() || style.border_width > 0.0; + + renderer.with_layer(bounds, Vector::new(0, 0), |renderer| { + if is_scrollbar_visible { + renderer.fill_rectangle(renderer::Quad { + bounds: scrollbar.bounds, + background: style + .background + .unwrap_or(Background::Color(Color::TRANSPARENT)), + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + } + + if is_mouse_over + || self.state.is_scroller_grabbed() + || is_scrollbar_visible + { + renderer.fill_rectangle(renderer::Quad { + bounds: scrollbar.scroller.bounds, + background: Background::Color(style.scroller.color), + border_radius: style.scroller.border_radius, + border_width: style.scroller.border_width, + border_color: style.scroller.border_color, + }); + } + }); } else { self.content.draw( renderer, @@ -614,19 +656,19 @@ impl State { /// The scrollbar of a [`Scrollable`]. #[derive(Debug)] -pub struct Scrollbar { +struct Scrollbar { /// The outer bounds of the scrollable, including the [`Scrollbar`] and /// [`Scroller`]. - pub outer_bounds: Rectangle, + outer_bounds: Rectangle, /// The bounds of the [`Scrollbar`]. - pub bounds: Rectangle, + bounds: Rectangle, /// The margin within the [`Scrollbar`]. - pub margin: u16, + margin: u16, /// The bounds of the [`Scroller`]. - pub scroller: Scroller, + scroller: Scroller, } impl Scrollbar { @@ -661,38 +703,15 @@ impl Scrollbar { /// The handle of a [`Scrollbar`]. #[derive(Debug, Clone, Copy)] -pub struct Scroller { +struct Scroller { /// The bounds of the [`Scroller`]. - pub bounds: Rectangle, -} - -/// The renderer of a [`Scrollable`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Scrollable`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// The style supported by this renderer. - type Style: Default; - - /// Returns the [`Scrollbar`] given the bounds and content bounds of a - /// [`Scrollable`]. - fn scrollbar( - &self, - bounds: Rectangle, - content_bounds: Rectangle, - offset: u32, - scrollbar_width: u16, - scrollbar_margin: u16, - scroller_width: u16, - ) -> Option; + bounds: Rectangle, } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { fn from( -- cgit From edea093350e1b576e2b7db50c525e7fa5c3bea9f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 15:19:04 +0700 Subject: Move `Defaults` from `iced_graphics` to `iced_native` --- native/src/widget/button.rs | 3 +- native/src/widget/checkbox.rs | 8 +-- native/src/widget/column.rs | 5 +- native/src/widget/container.rs | 5 +- native/src/widget/image.rs | 3 +- native/src/widget/image/viewer.rs | 3 +- native/src/widget/pane_grid.rs | 3 +- native/src/widget/pane_grid/content.rs | 3 +- native/src/widget/pane_grid/title_bar.rs | 3 +- native/src/widget/pick_list.rs | 3 +- native/src/widget/progress_bar.rs | 8 +-- native/src/widget/radio.rs | 8 +-- native/src/widget/row.rs | 5 +- native/src/widget/rule.rs | 9 ++-- native/src/widget/scrollable.rs | 6 +-- native/src/widget/slider.rs | 6 ++- native/src/widget/space.rs | 10 ++-- native/src/widget/svg.rs | 11 ++--- native/src/widget/text.rs | 6 +-- native/src/widget/text_input.rs | 85 +++++++++++++------------------- native/src/widget/toggler.rs | 3 +- native/src/widget/tooltip.rs | 10 ++-- 22 files changed, 101 insertions(+), 105 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 1c7f80ef..2aeffd03 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -5,6 +5,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; +use crate::renderer; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, @@ -244,7 +245,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 579e4ee3..52113322 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -1,15 +1,15 @@ //! Show toggle controls using checkboxes. use std::hash::Hash; -use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; use crate::mouse; +use crate::renderer; use crate::text; use crate::touch; use crate::{ - Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Row, - Text, Widget, + Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, + Rectangle, Row, Text, Widget, }; /// A box that can be checked. @@ -182,7 +182,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 7cf6d345..e7ce0041 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -4,6 +4,7 @@ use std::hash::Hash; use crate::event::{self, Event}; use crate::layout; use crate::overlay; +use crate::renderer; use crate::{ Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, Widget, @@ -165,13 +166,13 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, ) { for (child, layout) in self.children.iter().zip(layout.children()) { - child.draw(renderer, defaults, layout, cursor_position, viewport); + child.draw(renderer, style, layout, cursor_position, viewport); } } diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index af40f2ab..92869873 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -5,6 +5,7 @@ use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; use crate::overlay; +use crate::renderer; use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, Widget, @@ -175,14 +176,14 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, ) { self.content.draw( renderer, - defaults, + style, layout.children().next().unwrap(), cursor_position, viewport, diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 1607a596..b6b8dc1f 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -3,6 +3,7 @@ pub mod viewer; pub use viewer::Viewer; use crate::layout; +use crate::renderer; use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::{ @@ -92,7 +93,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index d483ed61..63087f5f 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -3,6 +3,7 @@ use crate::event::{self, Event}; use crate::image; use crate::layout; use crate::mouse; +use crate::renderer; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, @@ -283,7 +284,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index b4a8cdb1..1e63fdeb 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -32,6 +32,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; +use crate::renderer; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, @@ -475,7 +476,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index e94955f7..22b3a310 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -3,6 +3,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::overlay; use crate::pane_grid::{self, TitleBar}; +use crate::renderer; use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; /// The content of a [`Pane`]. @@ -57,7 +58,7 @@ where pub fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 9b0b7c78..ce9249d2 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -3,6 +3,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::overlay; use crate::pane_grid; +use crate::renderer; use crate::{ Clipboard, Element, Hasher, Layout, Padding, Point, Rectangle, Size, }; @@ -85,7 +86,7 @@ where pub fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 73b01b01..ed688a61 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -5,6 +5,7 @@ use crate::layout; use crate::mouse; use crate::overlay; use crate::overlay::menu::{self, Menu}; +use crate::renderer; use crate::text; use crate::touch; use crate::{ @@ -322,7 +323,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index d8cf5376..98dd9989 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -1,7 +1,7 @@ //! Provide progress feedback to your users. -use crate::{ - layout, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, -}; +use crate::layout; +use crate::renderer; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::{hash::Hash, ops::RangeInclusive}; @@ -93,7 +93,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index c6955079..ba9bd9aa 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -1,15 +1,15 @@ //! Create choices using radio buttons. use std::hash::Hash; -use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; use crate::mouse; +use crate::renderer; use crate::text; use crate::touch; use crate::{ - Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Row, - Text, Widget, + Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, + Rectangle, Row, Text, Widget, }; /// A circular button representing a choice. @@ -194,7 +194,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 7eb5ab55..af63c7da 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -2,6 +2,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::overlay; +use crate::renderer; use crate::{ Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, Widget, @@ -164,13 +165,13 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, ) { for (child, layout) in self.children.iter().zip(layout.children()) { - child.draw(renderer, defaults, layout, cursor_position, viewport); + child.draw(renderer, style, layout, cursor_position, viewport); } } diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 1fab77bc..24c4a51a 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -1,11 +1,10 @@ //! Display a horizontal or vertical rule for dividing content. +use crate::layout; +use crate::renderer; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::hash::Hash; -use crate::{ - layout, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, -}; - /// Display a horizontal or vertical rule for dividing content. #[derive(Debug, Copy, Clone)] pub struct Rule { @@ -68,7 +67,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 98357928..63da539f 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -425,7 +425,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, @@ -452,7 +452,7 @@ where renderer.with_layer(bounds, Vector::new(0, offset), |renderer| { self.content.draw( renderer, - defaults, + style, content_layout, cursor_position, &Rectangle { @@ -502,7 +502,7 @@ where } else { self.content.draw( renderer, - defaults, + style, content_layout, cursor_position, &Rectangle { diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index bcf811fe..7bdb72af 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -4,12 +4,14 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; +use crate::renderer; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, }; -use std::{hash::Hash, ops::RangeInclusive}; +use std::hash::Hash; +use std::ops::RangeInclusive; /// An horizontal bar and a handle that selects a single value from a range of /// values. @@ -246,7 +248,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index 9a70dab1..1bf8cd68 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -1,9 +1,9 @@ //! Distribute content vertically. -use std::hash::Hash; +use crate::layout; +use crate::renderer; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; -use crate::{ - layout, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, -}; +use std::hash::Hash; /// An amount of empty space. /// @@ -62,7 +62,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 737dd8d4..cce560cb 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -1,12 +1,11 @@ //! Display vector graphics in your application. use crate::layout; +use crate::renderer; use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; -use std::{ - hash::{Hash, Hasher as _}, - path::PathBuf, - sync::Arc, -}; +use std::hash::{Hash, Hasher as _}; +use std::path::PathBuf; +use std::sync::Arc; /// A vector graphics image. /// @@ -90,7 +89,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index ea1ba7ac..a2438d9c 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -135,7 +135,7 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, @@ -156,9 +156,9 @@ where renderer.fill_text(renderer::text::Section { content: &self.content, - size: self.size.map(f32::from), + size: f32::from(self.size.unwrap_or(renderer.default_size())), bounds: Rectangle { x, y, ..bounds }, - color: self.color, + color: self.color.unwrap_or(style.text_color), font: self.font, horizontal_alignment: self.horizontal_alignment, vertical_alignment: self.vertical_alignment, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index fe95eb95..93af04d1 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -15,6 +15,7 @@ use crate::event::{self, Event}; use crate::keyboard; use crate::layout; use crate::mouse::{self, click}; +use crate::renderer; use crate::text; use crate::touch; use crate::{ @@ -158,54 +159,6 @@ where } } -impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> -where - Renderer: self::Renderer, -{ - /// Draws the [`TextInput`] with the given [`Renderer`], overriding its - /// [`Value`] if provided. - pub fn draw( - &self, - renderer: &mut Renderer, - layout: Layout<'_>, - cursor_position: Point, - value: Option<&Value>, - ) { - // TODO - // let value = value.unwrap_or(&self.value); - // let bounds = layout.bounds(); - // let text_bounds = layout.children().next().unwrap().bounds(); - - // if self.is_secure { - // self::Renderer::draw( - // renderer, - // bounds, - // text_bounds, - // cursor_position, - // self.font, - // self.size.unwrap_or(renderer.default_size()), - // &self.placeholder, - // &value.secure(), - // &self.state, - // &self.style, - // ) - // } else { - // self::Renderer::draw( - // renderer, - // bounds, - // text_bounds, - // cursor_position, - // self.font, - // self.size.unwrap_or(renderer.default_size()), - // &self.placeholder, - // value, - // &self.state, - // &self.style, - // ) - // } - } -} - impl<'a, Message, Renderer> Widget for TextInput<'a, Message, Renderer> where @@ -627,12 +580,44 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + _style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, ) { - self.draw(renderer, layout, cursor_position, None) + + // TODO + // let value = value.unwrap_or(&self.value); + // let bounds = layout.bounds(); + // let text_bounds = layout.children().next().unwrap().bounds(); + + // if self.is_secure { + // self::Renderer::draw( + // renderer, + // bounds, + // text_bounds, + // cursor_position, + // self.font, + // self.size.unwrap_or(renderer.default_size()), + // &self.placeholder, + // &value.secure(), + // &self.state, + // &self.style, + // ) + // } else { + // self::Renderer::draw( + // renderer, + // bounds, + // text_bounds, + // cursor_position, + // self.font, + // self.size.unwrap_or(renderer.default_size()), + // &self.placeholder, + // value, + // &self.state, + // &self.style, + // ) + // } } fn hash_layout(&self, state: &mut Hasher) { diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 4a1f1f5d..6c7fa97b 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -5,6 +5,7 @@ use crate::alignment; use crate::event; use crate::layout; use crate::mouse; +use crate::renderer; use crate::text; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, @@ -185,7 +186,7 @@ where fn draw( &self, renderer: &mut Renderer, - defaults: &Renderer::Defaults, + style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 83d04675..496cd41e 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -3,12 +3,12 @@ use std::hash::Hash; use iced_core::Rectangle; +use crate::event; +use crate::layout; +use crate::renderer; use crate::widget::container; use crate::widget::text::{self, Text}; -use crate::{ - event, layout, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Widget, -}; +use crate::{Clipboard, Element, Event, Hasher, Layout, Length, Point, Widget}; /// An element to display a widget over another. #[allow(missing_debug_implementations)] @@ -137,7 +137,7 @@ where fn draw( &self, _renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + style: &renderer::Style, _layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, -- cgit From d61cb58d92b6fcd520f665deb093f3747ffd5e5c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 15:36:32 +0700 Subject: Wire up `container` styling to `iced_native` --- native/src/widget/container.rs | 29 ++++++++++------------------- native/src/widget/pane_grid.rs | 5 ++--- native/src/widget/pane_grid/content.rs | 11 ++++------- native/src/widget/pane_grid/title_bar.rs | 9 +++------ native/src/widget/scrollable.rs | 5 +---- native/src/widget/tooltip.rs | 16 +++++++--------- 6 files changed, 27 insertions(+), 48 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 92869873..99bc3d49 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -13,11 +13,13 @@ use crate::{ use std::u32; +pub use iced_style::container::{Style, StyleSheet}; + /// An element decorating some content. /// /// It is normally used for alignment purposes. #[allow(missing_debug_implementations)] -pub struct Container<'a, Message, Renderer: self::Renderer> { +pub struct Container<'a, Message, Renderer> { padding: Padding, width: Length, height: Length, @@ -25,13 +27,13 @@ pub struct Container<'a, Message, Renderer: self::Renderer> { max_height: u32, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, - style: Renderer::Style, + style: &'a dyn StyleSheet, content: Element<'a, Message, Renderer>, } impl<'a, Message, Renderer> Container<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { /// Creates an empty [`Container`]. pub fn new(content: T) -> Self @@ -46,7 +48,7 @@ where max_height: u32::MAX, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, - style: Renderer::Style::default(), + style: Default::default(), content: content.into(), } } @@ -106,8 +108,8 @@ where } /// Sets the style of the [`Container`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { + self.style = style; self } } @@ -115,7 +117,7 @@ where impl<'a, Message, Renderer> Widget for Container<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -211,21 +213,10 @@ where } } -/// The renderer of a [`Container`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Container`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 1e63fdeb..afecd681 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -27,7 +27,6 @@ pub use split::Split; pub use state::State; pub use title_bar::TitleBar; -use crate::container; use crate::event::{self, Event}; use crate::layout; use crate::mouse; @@ -318,7 +317,7 @@ pub struct ResizeEvent { impl<'a, Message, Renderer> Widget for PaneGrid<'a, Message, Renderer> where - Renderer: self::Renderer + container::Renderer, + Renderer: self::Renderer, { fn width(&self) -> Length { self.width @@ -565,7 +564,7 @@ where /// able to use a [`PaneGrid`] in your user interface. /// /// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + container::Renderer + Sized { +pub trait Renderer: crate::Renderer + Sized { /// The style supported by this renderer. type Style: Default; } diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index 22b3a310..7858c15d 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -13,7 +13,7 @@ use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; pub struct Content<'a, Message, Renderer: pane_grid::Renderer> { title_bar: Option>, body: Element<'a, Message, Renderer>, - style: ::Style, + style: &'a dyn container::StyleSheet, } impl<'a, Message, Renderer> Content<'a, Message, Renderer> @@ -39,11 +39,8 @@ where } /// Sets the style of the [`Content`]. - pub fn style( - mut self, - style: impl Into<::Style>, - ) -> Self { - self.style = style.into(); + pub fn style(mut self, style: &'a dyn container::StyleSheet) -> Self { + self.style = style; self } } @@ -217,7 +214,7 @@ where impl<'a, T, Message, Renderer> From for Content<'a, Message, Renderer> where T: Into>, - Renderer: pane_grid::Renderer + container::Renderer, + Renderer: pane_grid::Renderer, { fn from(element: T) -> Self { Self::new(element) diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index ce9249d2..22d3a9eb 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -17,7 +17,7 @@ pub struct TitleBar<'a, Message, Renderer: pane_grid::Renderer> { controls: Option>, padding: Padding, always_show_controls: bool, - style: ::Style, + style: &'a dyn container::StyleSheet, } impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer> @@ -54,11 +54,8 @@ where } /// Sets the style of the [`TitleBar`]. - pub fn style( - mut self, - style: impl Into<::Style>, - ) -> Self { - self.style = style.into(); + pub fn style(mut self, style: &'a dyn container::StyleSheet) -> Self { + self.style = style; self } diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 63da539f..ac5b3e4f 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -122,10 +122,7 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> { } /// Sets the style of the [`Scrollable`] . - pub fn style<'b>(mut self, style_sheet: &'b dyn StyleSheet) -> Self - where - 'b: 'a, - { + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { self.style_sheet = style_sheet; self } diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 496cd41e..4e8483ad 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -16,7 +16,7 @@ pub struct Tooltip<'a, Message, Renderer: self::Renderer> { content: Element<'a, Message, Renderer>, tooltip: Text, position: Position, - style: ::Style, + style: &'a dyn container::StyleSheet, gap: u16, padding: u16, } @@ -70,11 +70,11 @@ where } /// Sets the style of the [`Tooltip`]. - pub fn style( - mut self, - style: impl Into<::Style>, - ) -> Self { - self.style = style.into(); + pub fn style<'b>(mut self, style: &'b dyn container::StyleSheet) -> Self + where + 'b: 'a, + { + self.style = style; self } } @@ -160,9 +160,7 @@ where /// /// [`Tooltip`]: struct.Tooltip.html /// [renderer]: ../../renderer/index.html -pub trait Renderer: - crate::Renderer + text::Renderer + container::Renderer -{ +pub trait Renderer: crate::Renderer + text::Renderer { /// The default padding of a [`Tooltip`] drawn by this renderer. const DEFAULT_PADDING: u16; } -- cgit From 945f69e567d1766c82f77d3299d2d619d56d3add Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 15:44:03 +0700 Subject: Draw styling in `Widget::draw` for `Container` --- native/src/widget/container.rs | 44 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 99bc3d49..84c745e2 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -7,8 +7,8 @@ use crate::layout; use crate::overlay; use crate::renderer; use crate::{ - Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, - Widget, + Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, + Point, Rectangle, Widget, }; use std::u32; @@ -27,7 +27,7 @@ pub struct Container<'a, Message, Renderer> { max_height: u32, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, - style: &'a dyn StyleSheet, + style_sheet: &'a dyn StyleSheet, content: Element<'a, Message, Renderer>, } @@ -48,7 +48,7 @@ where max_height: u32::MAX, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, - style: Default::default(), + style_sheet: Default::default(), content: content.into(), } } @@ -108,8 +108,8 @@ where } /// Sets the style of the [`Container`]. - pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { - self.style = style; + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } @@ -178,14 +178,22 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + renderer_style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, ) { + let style = self.style_sheet.style(); + + draw_background(renderer, &style, layout.bounds()); + self.content.draw( renderer, - style, + &renderer::Style { + text_color: style + .text_color + .unwrap_or(renderer_style.text_color), + }, layout.children().next().unwrap(), cursor_position, viewport, @@ -213,6 +221,26 @@ where } } +pub fn draw_background( + renderer: &mut Renderer, + style: &Style, + bounds: Rectangle, +) where + Renderer: crate::Renderer, +{ + if style.background.is_some() || style.border_width > 0.0 { + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style + .background + .unwrap_or(Background::Color(Color::TRANSPARENT)), + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + } +} + impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where -- cgit From 3140cdc4babcefc444f1c1d30eb0f5f4ed1df054 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:02:30 +0700 Subject: Wire up styling to `Button` in `iced_native` --- native/src/widget/button.rs | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 2aeffd03..77148673 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -11,8 +11,11 @@ use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, Widget, }; + use std::hash::Hash; +pub use iced_style::button::{Style, StyleSheet}; + /// A generic widget that produces a message when pressed. /// /// ``` @@ -54,7 +57,7 @@ use std::hash::Hash; /// } /// ``` #[allow(missing_debug_implementations)] -pub struct Button<'a, Message, Renderer: self::Renderer> { +pub struct Button<'a, Message, Renderer> { state: &'a mut State, content: Element<'a, Message, Renderer>, on_press: Option, @@ -63,13 +66,13 @@ pub struct Button<'a, Message, Renderer: self::Renderer> { min_width: u32, min_height: u32, padding: Padding, - style: Renderer::Style, + style: &'a dyn StyleSheet, } impl<'a, Message, Renderer> Button<'a, Message, Renderer> where Message: Clone, - Renderer: self::Renderer, + Renderer: crate::Renderer, { /// Creates a new [`Button`] with some local [`State`] and the given /// content. @@ -85,8 +88,8 @@ where height: Length::Shrink, min_width: 0, min_height: 0, - padding: Renderer::DEFAULT_PADDING, - style: Renderer::Style::default(), + padding: Padding::new(5), + style: Default::default(), } } @@ -128,8 +131,8 @@ where } /// Sets the style of the [`Button`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { + self.style = style; self } } @@ -151,7 +154,7 @@ impl<'a, Message, Renderer> Widget for Button<'a, Message, Renderer> where Message: Clone, - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -268,25 +271,11 @@ where } } -/// The renderer of a [`Button`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Button`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// The default padding of a [`Button`]. - const DEFAULT_PADDING: Padding; - - /// The style supported by this renderer. - type Style: Default; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, { fn from( button: Button<'a, Message, Renderer>, -- cgit From 7a876c8b2918ae90cedfd82d1881cf6406811eeb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:10:16 +0700 Subject: Implement `Widget::draw` for `Button` --- native/src/widget/button.rs | 67 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 77148673..a05210fd 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -8,8 +8,8 @@ use crate::overlay; use crate::renderer; use crate::touch; use crate::{ - Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, - Widget, + Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, + Point, Rectangle, Vector, Widget, }; use std::hash::Hash; @@ -66,7 +66,7 @@ pub struct Button<'a, Message, Renderer> { min_width: u32, min_height: u32, padding: Padding, - style: &'a dyn StyleSheet, + style_sheet: &'a dyn StyleSheet, } impl<'a, Message, Renderer> Button<'a, Message, Renderer> @@ -89,7 +89,7 @@ where min_width: 0, min_height: 0, padding: Padding::new(5), - style: Default::default(), + style_sheet: Default::default(), } } @@ -131,8 +131,8 @@ where } /// Sets the style of the [`Button`]. - pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { - self.style = style; + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } @@ -248,11 +248,64 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, ) { + let bounds = layout.bounds(); + let content_layout = layout.children().next().unwrap(); + + let is_mouse_over = bounds.contains(cursor_position); + + let styling = if self.on_press.is_none() { + self.style_sheet.disabled() + } else if is_mouse_over { + if self.state.is_pressed { + self.style_sheet.pressed() + } else { + self.style_sheet.hovered() + } + } else { + self.style_sheet.active() + }; + + if styling.background.is_some() || styling.border_width > 0.0 { + if styling.shadow_offset != Vector::default() { + // TODO: Implement proper shadow support + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + x: bounds.x + styling.shadow_offset.x, + y: bounds.y + styling.shadow_offset.y, + ..bounds + }, + background: Background::Color([0.0, 0.0, 0.0, 0.5].into()), + border_radius: styling.border_radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + } + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: styling + .background + .unwrap_or(Background::Color(Color::TRANSPARENT)), + border_radius: styling.border_radius, + border_width: styling.border_width, + border_color: styling.border_color, + }); + } + + self.content.draw( + renderer, + &renderer::Style { + text_color: styling.text_color, + }, + content_layout, + cursor_position, + &bounds, + ); } fn hash_layout(&self, state: &mut Hasher) { -- cgit From 5130e98dc873f57279f7fa7acb0b7e6d12fb7edf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:45:53 +0700 Subject: Implement `Widget::mouse_interaction` for `Container` --- native/src/widget/container.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 84c745e2..006e07c6 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -4,6 +4,7 @@ use std::hash::Hash; use crate::alignment::{self, Alignment}; use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{ @@ -175,6 +176,19 @@ where ) } + fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + self.content.widget.mouse_interaction( + layout.children().next().unwrap(), + viewport, + cursor_position, + ) + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 519a0cc233ac915c3a5df2bd81d1375edb05a4ae Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:47:37 +0700 Subject: Implement `Widget::mouse_interaction` for `Column` --- native/src/widget/column.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index e7ce0041..1d2c8485 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -3,6 +3,7 @@ use std::hash::Hash; use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{ @@ -163,6 +164,26 @@ where .fold(event::Status::Ignored, event::Status::merge) } + fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + self.children + .iter() + .zip(layout.children()) + .map(|(child, layout)| { + child.widget.mouse_interaction( + layout, + viewport, + cursor_position, + ) + }) + .max() + .unwrap_or_default() + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 14dc750149b6cfaa49ba8fe3533343e0594fc2a3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:48:39 +0700 Subject: Implement `Widget::mouse_interaction` for `Row` --- native/src/widget/row.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index af63c7da..af83f106 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -1,6 +1,7 @@ //! Distribute content horizontally. use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{ @@ -162,6 +163,26 @@ where .fold(event::Status::Ignored, event::Status::merge) } + fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + self.children + .iter() + .zip(layout.children()) + .map(|(child, layout)| { + child.widget.mouse_interaction( + layout, + viewport, + cursor_position, + ) + }) + .max() + .unwrap_or_default() + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 9a4fb82b5818f10e96d2f185a7e5a1f1fce3305c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:53:50 +0700 Subject: Implement `Widget::mouse_interaction` for `Scrollable` --- native/src/widget/scrollable.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index ac5b3e4f..76badbde 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -419,6 +419,45 @@ where event::Status::Ignored } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let bounds = layout.bounds(); + let content_layout = layout.children().next().unwrap(); + let content_bounds = content_layout.bounds(); + let scrollbar = self.scrollbar(bounds, content_bounds); + + let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over_scrollbar = scrollbar + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false); + + if is_mouse_over_scrollbar || self.state.is_scroller_grabbed() { + mouse::Interaction::Idle + } else { + let offset = self.state.offset(bounds, content_bounds); + + let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { + Point::new(cursor_position.x, cursor_position.y + offset as f32) + } else { + Point::new(cursor_position.x, -1.0) + }; + + self.content.mouse_interaction( + content_layout, + &Rectangle { + y: bounds.y + offset as f32, + ..bounds + }, + cursor_position, + ) + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 4f5f444d7c507105d025471fbe930e50653c05bf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 18 Oct 2021 16:59:42 +0700 Subject: Implement `Widget::mouse_interaction` for `Button` --- native/src/widget/button.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index a05210fd..a654cf12 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -245,6 +245,22 @@ where event::Status::Ignored } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let is_mouse_over = layout.bounds().contains(cursor_position); + let is_disabled = self.on_press.is_none(); + + if is_mouse_over && !is_disabled { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, @@ -257,8 +273,9 @@ where let content_layout = layout.children().next().unwrap(); let is_mouse_over = bounds.contains(cursor_position); + let is_disabled = self.on_press.is_none(); - let styling = if self.on_press.is_none() { + let styling = if is_disabled { self.style_sheet.disabled() } else if is_mouse_over { if self.state.is_pressed { -- cgit From 11bcb1342796a6fabc7c5b89a15c22c754b014ce Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 15:50:42 +0700 Subject: Wire up styling to `Slider` in `iced_native` --- native/src/widget/slider.rs | 48 ++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 7bdb72af..24b6bf6d 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -13,6 +13,8 @@ use crate::{ use std::hash::Hash; use std::ops::RangeInclusive; +pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet}; + /// An horizontal bar and a handle that selects a single value from a range of /// values. /// @@ -23,9 +25,8 @@ use std::ops::RangeInclusive; /// /// # Example /// ``` -/// # use iced_native::{slider, renderer::Null}; +/// # use iced_native::slider::{self, Slider}; /// # -/// # pub type Slider<'a, T, Message> = iced_native::Slider<'a, T, Message, Null>; /// #[derive(Clone)] /// pub enum Message { /// SliderChanged(f32), @@ -39,7 +40,7 @@ use std::ops::RangeInclusive; /// /// ![Slider drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/slider.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Slider<'a, T, Message, Renderer: self::Renderer> { +pub struct Slider<'a, T, Message> { state: &'a mut State, range: RangeInclusive, step: T, @@ -48,15 +49,16 @@ pub struct Slider<'a, T, Message, Renderer: self::Renderer> { on_release: Option, width: Length, height: u16, - style: Renderer::Style, + style_sheet: &'a dyn StyleSheet, } -impl<'a, T, Message, Renderer> Slider<'a, T, Message, Renderer> +impl<'a, T, Message> Slider<'a, T, Message> where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Renderer: self::Renderer, { + pub const DEFAULT_HEIGHT: u16 = 22; + /// Creates a new [`Slider`]. /// /// It expects: @@ -95,8 +97,8 @@ where on_change: Box::new(on_change), on_release: None, width: Length::Fill, - height: Renderer::DEFAULT_HEIGHT, - style: Renderer::Style::default(), + height: Self::DEFAULT_HEIGHT, + style_sheet: Default::default(), } } @@ -124,8 +126,8 @@ where } /// Sets the style of the [`Slider`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet; self } @@ -150,11 +152,11 @@ impl State { } impl<'a, T, Message, Renderer> Widget - for Slider<'a, T, Message, Renderer> + for Slider<'a, T, Message> where T: Copy + Into + num_traits::FromPrimitive, Message: Clone, - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -275,30 +277,14 @@ where } } -/// The renderer of a [`Slider`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Slider`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; - - /// The default height of a [`Slider`]. - const DEFAULT_HEIGHT: u16; -} - -impl<'a, T, Message, Renderer> From> +impl<'a, T, Message, Renderer> From> for Element<'a, Message, Renderer> where T: 'a + Copy + Into + num_traits::FromPrimitive, Message: 'a + Clone, - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, { - fn from( - slider: Slider<'a, T, Message, Renderer>, - ) -> Element<'a, Message, Renderer> { + fn from(slider: Slider<'a, T, Message>) -> Element<'a, Message, Renderer> { Element::new(slider) } } -- cgit From c800fd07c3460d90a120fe30fc0cd7503d829f68 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 16:28:12 +0700 Subject: Implement `Widget::draw` for `Slider` --- native/src/widget/slider.rs | 95 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 14 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 24b6bf6d..31a5965b 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -7,7 +7,8 @@ use crate::mouse; use crate::renderer; use crate::touch; use crate::{ - Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, + Background, Clipboard, Color, Element, Hasher, Layout, Length, Point, + Rectangle, Size, Widget, }; use std::hash::Hash; @@ -250,23 +251,89 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // let start = *self.range.start(); - // let end = *self.range.end(); - - // renderer.draw( - // layout.bounds(), - // cursor_position, - // start.into() as f32..=end.into() as f32, - // self.value.into() as f32, - // self.state.is_dragging, - // &self.style, - // ) + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + let style = if self.state.is_dragging { + self.style_sheet.dragging() + } else if is_mouse_over { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + let rail_y = bounds.y + (bounds.height / 2.0).round(); + + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: rail_y, + width: bounds.width, + height: 2.0, + }, + background: Background::Color(style.rail_colors.0), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: rail_y + 2.0, + width: bounds.width, + height: 2.0, + }, + background: Background::Color(style.rail_colors.1), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + + let (handle_width, handle_height, handle_border_radius) = match style + .handle + .shape + { + HandleShape::Circle { radius } => { + (radius * 2.0, radius * 2.0, radius) + } + HandleShape::Rectangle { + width, + border_radius, + } => (f32::from(width), f32::from(bounds.height), border_radius), + }; + + let value = self.value.into() as f32; + let (range_start, range_end) = { + let (start, end) = self.range.clone().into_inner(); + + (start.into() as f32, end.into() as f32) + }; + + let handle_offset = if range_start >= range_end { + 0.0 + } else { + (bounds.width - handle_width) * (value - range_start) + / (range_end - range_start) + }; + + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + x: bounds.x + handle_offset.round(), + y: rail_y - handle_height / 2.0, + width: handle_width, + height: handle_height, + }, + background: Background::Color(style.handle.color), + border_radius: handle_border_radius, + border_width: style.handle.border_width, + border_color: style.handle.border_color, + }); } fn hash_layout(&self, state: &mut Hasher) { -- cgit From 954d6349a8cd5505d99403285ce9617c65a63a2b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 16:28:27 +0700 Subject: Implement `Widget::mouse_interaction` for `Slider` --- native/src/widget/slider.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 31a5965b..60124160 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -336,6 +336,24 @@ where }); } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + if self.state.is_dragging { + mouse::Interaction::Grabbing + } else if is_mouse_over { + mouse::Interaction::Grab + } else { + mouse::Interaction::default() + } + } + fn hash_layout(&self, state: &mut Hasher) { struct Marker; std::any::TypeId::of::().hash(state); -- cgit From e914888f57394e4b67b40e42f1ad9df4ae8147e6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 18:40:39 +0700 Subject: Implement `Widget::draw` for `TextInput` --- native/src/widget/checkbox.rs | 9 +- native/src/widget/pick_list.rs | 2 +- native/src/widget/radio.rs | 9 +- native/src/widget/text.rs | 48 +---- native/src/widget/text_input.rs | 395 ++++++++++++++++++++++++++++------------ native/src/widget/toggler.rs | 9 +- native/src/widget/tooltip.rs | 4 +- 7 files changed, 297 insertions(+), 179 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 52113322..c307d776 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -5,7 +5,6 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; -use crate::text; use crate::touch; use crate::{ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, @@ -30,7 +29,7 @@ use crate::{ /// /// ![Checkbox drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Checkbox { +pub struct Checkbox { is_checked: bool, on_toggle: Box Message>, label: String, @@ -43,7 +42,7 @@ pub struct Checkbox { style: Renderer::Style, } -impl +impl Checkbox { /// Creates a new [`Checkbox`]. @@ -120,7 +119,7 @@ impl impl Widget for Checkbox where - Renderer: self::Renderer + text::Renderer, + Renderer: self::Renderer + renderer::Text, { fn width(&self) -> Length { self.width @@ -239,7 +238,7 @@ pub trait Renderer: crate::Renderer { impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + text::Renderer, + Renderer: 'a + self::Renderer + renderer::Text, Message: 'a, { fn from( diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index ed688a61..761cfcc8 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -366,7 +366,7 @@ where /// able to use a [`PickList`] in your user interface. /// /// [renderer]: crate::renderer -pub trait Renderer: text::Renderer + menu::Renderer { +pub trait Renderer: renderer::Text + menu::Renderer { /// The default padding of a [`PickList`]. const DEFAULT_PADDING: Padding; diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index ba9bd9aa..3d6d22cc 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -5,7 +5,6 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; -use crate::text; use crate::touch; use crate::{ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, @@ -39,7 +38,7 @@ use crate::{ /// /// ![Radio buttons drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/radio.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Radio { +pub struct Radio { is_selected: bool, on_click: Message, label: String, @@ -52,7 +51,7 @@ pub struct Radio { style: Renderer::Style, } -impl +impl Radio where Message: Clone, @@ -135,7 +134,7 @@ where impl Widget for Radio where Message: Clone, - Renderer: self::Renderer + text::Renderer, + Renderer: self::Renderer + renderer::Text, { fn width(&self) -> Length { self.width @@ -260,7 +259,7 @@ impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + self::Renderer + text::Renderer, + Renderer: 'a + self::Renderer + renderer::Text, { fn from(radio: Radio) -> Element<'a, Message, Renderer> { Element::new(radio) diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index a2438d9c..78bfa4e2 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -24,7 +24,7 @@ use std::hash::Hash; /// /// ![Text drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text.png?raw=true) #[derive(Debug)] -pub struct Text { +pub struct Text { content: String, size: Option, color: Option, @@ -35,7 +35,7 @@ pub struct Text { vertical_alignment: alignment::Vertical, } -impl Text { +impl Text { /// Create a new fragment of [`Text`] with the given contents. pub fn new>(label: T) -> Self { Text { @@ -103,7 +103,7 @@ impl Text { impl Widget for Text where - Renderer: self::Renderer, + Renderer: renderer::Text, { fn width(&self) -> Length { self.width @@ -176,55 +176,17 @@ where } } -/// The renderer of a [`Text`] fragment. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use [`Text`] in your user interface. -/// -/// [renderer]: crate::Renderer -pub trait Renderer: renderer::Text { - /// Returns the default size of [`Text`]. - fn default_size(&self) -> u16; - - /// Measures the [`Text`] in the given bounds and returns the minimum - /// boundaries that can fit the contents. - fn measure( - &self, - content: &str, - size: u16, - font: Self::Font, - bounds: Size, - ) -> (f32, f32); - - /// Tests whether the provided point is within the boundaries of [`Text`] - /// laid out with the given parameters, returning information about - /// the nearest character. - /// - /// If `nearest_only` is true, the hit test does not consider whether the - /// the point is interior to any glyph bounds, returning only the character - /// with the nearest centeroid. - fn hit_test( - &self, - contents: &str, - size: f32, - font: Self::Font, - bounds: Size, - point: Point, - nearest_only: bool, - ) -> Option; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: self::Renderer + 'a, + Renderer: renderer::Text + 'a, { fn from(text: Text) -> Element<'a, Message, Renderer> { Element::new(text) } } -impl Clone for Text { +impl Clone for Text { fn clone(&self) -> Self { Self { content: self.content.clone(), diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 93af04d1..22cb9092 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -11,20 +11,22 @@ pub use value::Value; use editor::Editor; +use crate::alignment; use crate::event::{self, Event}; use crate::keyboard; use crate::layout; use crate::mouse::{self, click}; use crate::renderer; -use crate::text; use crate::touch; use crate::{ - Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, - Size, Widget, + Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, + Point, Rectangle, Size, Vector, Widget, }; use std::u32; +pub use iced_style::text_input::{Style, StyleSheet}; + /// A field that can be filled with text. /// /// # Example @@ -50,7 +52,7 @@ use std::u32; /// ``` /// ![Text input drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text_input.png?raw=true) #[allow(missing_debug_implementations)] -pub struct TextInput<'a, Message, Renderer: self::Renderer> { +pub struct TextInput<'a, Message, Renderer: renderer::Text> { state: &'a mut State, placeholder: String, value: Value, @@ -62,13 +64,13 @@ pub struct TextInput<'a, Message, Renderer: self::Renderer> { size: Option, on_change: Box Message>, on_submit: Option, - style: Renderer::Style, + style_sheet: &'a dyn StyleSheet, } impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> where Message: Clone, - Renderer: self::Renderer, + Renderer: renderer::Text, { /// Creates a new [`TextInput`]. /// @@ -98,7 +100,7 @@ where size: None, on_change: Box::new(on_change), on_submit: None, - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -148,8 +150,8 @@ where } /// Sets the style of the [`TextInput`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet.into(); self } @@ -163,7 +165,7 @@ impl<'a, Message, Renderer> Widget for TextInput<'a, Message, Renderer> where Message: Clone, - Renderer: self::Renderer, + Renderer: renderer::Text, { fn width(&self) -> Length { self.width @@ -229,7 +231,8 @@ where self.value.clone() }; - renderer.find_cursor_position( + find_cursor_position( + renderer, text_layout.bounds(), self.font, self.size, @@ -248,16 +251,16 @@ where if self.is_secure { self.state.cursor.select_all(&self.value); } else { - let position = renderer - .find_cursor_position( - text_layout.bounds(), - self.font, - self.size, - &self.value, - &self.state, - target, - ) - .unwrap_or(0); + let position = find_cursor_position( + renderer, + text_layout.bounds(), + self.font, + self.size, + &self.value, + &self.state, + target, + ) + .unwrap_or(0); self.state.cursor.select_range( self.value.previous_start_of_word(position), @@ -296,16 +299,16 @@ where self.value.clone() }; - let position = renderer - .find_cursor_position( - text_layout.bounds(), - self.font, - self.size, - &value, - &self.state, - target, - ) - .unwrap_or(0); + let position = find_cursor_position( + renderer, + text_layout.bounds(), + self.font, + self.size, + &value, + &self.state, + target, + ) + .unwrap_or(0); self.state.cursor.select_range( self.state.cursor.start(&value), @@ -585,39 +588,164 @@ where cursor_position: Point, _viewport: &Rectangle, ) { + let secure_value = self.is_secure.then(|| self.value.secure()); + let value = secure_value.as_ref().unwrap_or(&self.value); + + let bounds = layout.bounds(); + let text_bounds = layout.children().next().unwrap().bounds(); - // TODO - // let value = value.unwrap_or(&self.value); - // let bounds = layout.bounds(); - // let text_bounds = layout.children().next().unwrap().bounds(); - - // if self.is_secure { - // self::Renderer::draw( - // renderer, - // bounds, - // text_bounds, - // cursor_position, - // self.font, - // self.size.unwrap_or(renderer.default_size()), - // &self.placeholder, - // &value.secure(), - // &self.state, - // &self.style, - // ) - // } else { - // self::Renderer::draw( - // renderer, - // bounds, - // text_bounds, - // cursor_position, - // self.font, - // self.size.unwrap_or(renderer.default_size()), - // &self.placeholder, - // value, - // &self.state, - // &self.style, - // ) - // } + let is_mouse_over = bounds.contains(cursor_position); + + let style = if self.state.is_focused() { + self.style_sheet.focused() + } else if is_mouse_over { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style.background, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + + let text = value.to_string(); + let size = self.size.unwrap_or(renderer.default_size()); + + let (cursor, offset) = if self.state.is_focused() { + match self.state.cursor.state(&value) { + cursor::State::Index(position) => { + let (text_value_width, offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + position, + self.font, + ); + + ( + Some(renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + text_value_width, + y: text_bounds.y, + width: 1.0, + height: text_bounds.height, + }, + background: Background::Color( + self.style_sheet.value_color(), + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }), + offset, + ) + } + cursor::State::Selection { start, end } => { + let left = start.min(end); + let right = end.max(start); + + let (left_position, left_offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + left, + self.font, + ); + + let (right_position, right_offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + right, + self.font, + ); + + let width = right_position - left_position; + + ( + Some(renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + left_position, + y: text_bounds.y, + width, + height: text_bounds.height, + }, + background: Background::Color( + self.style_sheet.selection_color(), + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }), + if end == right { + right_offset + } else { + left_offset + }, + ) + } + } + } else { + (None, 0.0) + }; + + let text_width = renderer.measure_width( + if text.is_empty() { + &self.placeholder + } else { + &text + }, + size, + self.font, + ); + + let render = |renderer: &mut Renderer| { + if let Some(cursor) = cursor { + renderer.fill_rectangle(cursor); + } + + renderer.fill_text(renderer::text::Section { + content: if text.is_empty() { + &self.placeholder + } else { + &text + }, + color: if text.is_empty() { + self.style_sheet.placeholder_color() + } else { + self.style_sheet.value_color() + }, + font: self.font, + bounds: Rectangle { + y: text_bounds.center_y(), + width: f32::INFINITY, + ..text_bounds + }, + size: f32::from(size), + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Center, + }); + }; + + if text_width > text_bounds.width { + renderer.with_layer( + text_bounds, + Vector::new(offset as u32, 0), + render, + ); + } else { + render(renderer); + } } fn hash_layout(&self, state: &mut Hasher) { @@ -632,65 +760,11 @@ where } } -/// The renderer of a [`TextInput`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`TextInput`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: text::Renderer + Sized { - /// The style supported by this renderer. - type Style: Default; - - /// Returns the width of the value of the [`TextInput`]. - fn measure_value(&self, value: &str, size: u16, font: Self::Font) -> f32; - - /// Returns the current horizontal offset of the value of the - /// [`TextInput`]. - /// - /// This is the amount of horizontal scrolling applied when the [`Value`] - /// does not fit the [`TextInput`]. - fn offset( - &self, - text_bounds: Rectangle, - font: Self::Font, - size: u16, - value: &Value, - state: &State, - ) -> f32; - - /// Computes the position of the text cursor at the given X coordinate of - /// a [`TextInput`]. - fn find_cursor_position( - &self, - text_bounds: Rectangle, - font: Self::Font, - size: Option, - value: &Value, - state: &State, - x: f32, - ) -> Option { - let size = size.unwrap_or(self.default_size()); - - let offset = self.offset(text_bounds, font, size, &value, &state); - - self.hit_test( - &value.to_string(), - size.into(), - font, - Size::INFINITY, - Point::new(x + offset, text_bounds.height / 2.0), - true, - ) - .map(text::Hit::cursor) - } -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + self::Renderer, + Renderer: 'a + renderer::Text, { fn from( text_input: TextInput<'a, Message, Renderer>, @@ -781,3 +855,88 @@ mod platform { } } } + +fn offset( + renderer: &Renderer, + text_bounds: Rectangle, + font: Renderer::Font, + size: u16, + value: &Value, + state: &State, +) -> f32 +where + Renderer: renderer::Text, +{ + if state.is_focused() { + let cursor = state.cursor(); + + let focus_position = match cursor.state(value) { + cursor::State::Index(i) => i, + cursor::State::Selection { end, .. } => end, + }; + + let (_, offset) = measure_cursor_and_scroll_offset( + renderer, + text_bounds, + value, + size, + focus_position, + font, + ); + + offset + } else { + 0.0 + } +} + +fn measure_cursor_and_scroll_offset( + renderer: &Renderer, + text_bounds: Rectangle, + value: &Value, + size: u16, + cursor_index: usize, + font: Renderer::Font, +) -> (f32, f32) +where + Renderer: renderer::Text, +{ + let text_before_cursor = value.until(cursor_index).to_string(); + + let text_value_width = + renderer.measure_width(&text_before_cursor, size, font); + + let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0); + + (text_value_width, offset) +} + +/// Computes the position of the text cursor at the given X coordinate of +/// a [`TextInput`]. +fn find_cursor_position( + renderer: &Renderer, + text_bounds: Rectangle, + font: Renderer::Font, + size: Option, + value: &Value, + state: &State, + x: f32, +) -> Option +where + Renderer: renderer::Text, +{ + let size = size.unwrap_or(renderer.default_size()); + + let offset = offset(renderer, text_bounds, font, size, &value, &state); + + renderer + .hit_test( + &value.to_string(), + size.into(), + font, + Size::INFINITY, + Point::new(x + offset, text_bounds.height / 2.0), + true, + ) + .map(renderer::text::Hit::cursor) +} diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 6c7fa97b..46a9850b 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -6,7 +6,6 @@ use crate::event; use crate::layout; use crate::mouse; use crate::renderer; -use crate::text; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, Rectangle, Row, Text, Widget, @@ -28,7 +27,7 @@ use crate::{ /// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b)); /// ``` #[allow(missing_debug_implementations)] -pub struct Toggler { +pub struct Toggler { is_active: bool, on_toggle: Box Message>, label: Option, @@ -41,7 +40,7 @@ pub struct Toggler { style: Renderer::Style, } -impl +impl Toggler { /// Creates a new [`Toggler`]. @@ -119,7 +118,7 @@ impl impl Widget for Toggler where - Renderer: self::Renderer + text::Renderer, + Renderer: self::Renderer + renderer::Text, { fn width(&self) -> Length { self.width @@ -246,7 +245,7 @@ pub trait Renderer: crate::Renderer { impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + text::Renderer, + Renderer: 'a + self::Renderer + renderer::Text, Message: 'a, { fn from( diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 4e8483ad..c2bc8af0 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -7,7 +7,7 @@ use crate::event; use crate::layout; use crate::renderer; use crate::widget::container; -use crate::widget::text::{self, Text}; +use crate::widget::text::Text; use crate::{Clipboard, Element, Event, Hasher, Layout, Length, Point, Widget}; /// An element to display a widget over another. @@ -160,7 +160,7 @@ where /// /// [`Tooltip`]: struct.Tooltip.html /// [renderer]: ../../renderer/index.html -pub trait Renderer: crate::Renderer + text::Renderer { +pub trait Renderer: renderer::Text { /// The default padding of a [`Tooltip`] drawn by this renderer. const DEFAULT_PADDING: u16; } -- cgit From cc560aca181202e827bfdc9afb6fc9fbe42f54d6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 18:45:45 +0700 Subject: Implement `Widget::mouse_interaction` for `TextInput` --- native/src/widget/text_input.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 22cb9092..0a2b19a3 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -580,6 +580,19 @@ where event::Status::Ignored } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + if layout.bounds().contains(cursor_position) { + mouse::Interaction::Text + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From d39ad717ed0ab85acbe935d7ab883166b36e7bc7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 19:06:53 +0700 Subject: Wire up styling to `Radio` in `iced_native` --- native/src/widget/radio.rs | 89 ++++++++++++++-------------------------------- native/src/widget/text.rs | 72 +++++++++++++++++++++++++------------ 2 files changed, 75 insertions(+), 86 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 3d6d22cc..0e1023b5 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -11,12 +11,14 @@ use crate::{ Rectangle, Row, Text, Widget, }; +pub use iced_style::radio::{Style, StyleSheet}; + /// A circular button representing a choice. /// /// # Example /// ``` -/// # type Radio = -/// # iced_native::Radio; +/// # type Radio<'a, Message> = +/// # iced_native::Radio<'a, Message, iced_native::renderer::Null>; /// # /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] /// pub enum Choice { @@ -38,7 +40,7 @@ use crate::{ /// /// ![Radio buttons drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/radio.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Radio { +pub struct Radio<'a, Message, Renderer: renderer::Text> { is_selected: bool, on_click: Message, label: String, @@ -48,14 +50,19 @@ pub struct Radio { text_size: Option, text_color: Option, font: Renderer::Font, - style: Renderer::Style, + style_sheet: &'a dyn StyleSheet, } -impl - Radio +impl<'a, Message, Renderer: renderer::Text> Radio<'a, Message, Renderer> where Message: Clone, { + /// The default size of a [`Radio`] button. + pub const DEFAULT_SIZE: u16 = 28; + + /// The default spacing of a [`Radio`] button. + pub const DEFAULT_SPACING: u16 = 15; + /// Creates a new [`Radio`] button. /// /// It expects: @@ -79,12 +86,12 @@ where on_click: f(value), label: label.into(), width: Length::Shrink, - size: ::DEFAULT_SIZE, - spacing: Renderer::DEFAULT_SPACING, //15 + size: Self::DEFAULT_SIZE, + spacing: Self::DEFAULT_SPACING, //15 text_size: None, text_color: None, font: Default::default(), - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -125,16 +132,17 @@ where } /// Sets the style of the [`Radio`] button. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } -impl Widget for Radio +impl<'a, Message, Renderer> Widget + for Radio<'a, Message, Renderer> where Message: Clone, - Renderer: self::Renderer + renderer::Text, + Renderer: renderer::Text, { fn width(&self) -> Length { self.width @@ -198,36 +206,6 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // let bounds = layout.bounds(); - // let mut children = layout.children(); - - // let radio_layout = children.next().unwrap(); - // let label_layout = children.next().unwrap(); - // let radio_bounds = radio_layout.bounds(); - - // let label = text::Renderer::draw( - // renderer, - // defaults, - // label_layout.bounds(), - // &self.label, - // self.text_size.unwrap_or(renderer.default_size()), - // self.font, - // self.text_color, - // alignment::Horizontal::Left, - // alignment::Vertical::Center, - // ); - - // let is_mouse_over = bounds.contains(cursor_position); - - // self::Renderer::draw( - // renderer, - // radio_bounds, - // self.is_selected, - // is_mouse_over, - // label, - // &self.style, - // ) } fn hash_layout(&self, state: &mut Hasher) { @@ -238,30 +216,15 @@ where } } -/// The renderer of a [`Radio`] button. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Radio`] button in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; - - /// The default size of a [`Radio`] button. - const DEFAULT_SIZE: u16; - - /// The default spacing of a [`Radio`] button. - const DEFAULT_SPACING: u16; -} - -impl<'a, Message, Renderer> From> +impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + self::Renderer + renderer::Text, + Renderer: 'a + renderer::Text, { - fn from(radio: Radio) -> Element<'a, Message, Renderer> { + fn from( + radio: Radio<'a, Message, Renderer>, + ) -> Element<'a, Message, Renderer> { Element::new(radio) } } diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 78bfa4e2..2432dbc8 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -140,29 +140,17 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { - let bounds = layout.bounds(); - - let x = match self.horizontal_alignment { - alignment::Horizontal::Left => bounds.x, - alignment::Horizontal::Center => bounds.center_x(), - alignment::Horizontal::Right => bounds.x + bounds.width, - }; - - let y = match self.vertical_alignment { - alignment::Vertical::Top => bounds.y, - alignment::Vertical::Center => bounds.center_y(), - alignment::Vertical::Bottom => bounds.y + bounds.height, - }; - - renderer.fill_text(renderer::text::Section { - content: &self.content, - size: f32::from(self.size.unwrap_or(renderer.default_size())), - bounds: Rectangle { x, y, ..bounds }, - color: self.color.unwrap_or(style.text_color), - font: self.font, - horizontal_alignment: self.horizontal_alignment, - vertical_alignment: self.vertical_alignment, - }); + draw( + renderer, + style, + layout, + &self.content, + self.font, + self.size, + self.color, + self.horizontal_alignment, + self.vertical_alignment, + ); } fn hash_layout(&self, state: &mut Hasher) { @@ -176,6 +164,44 @@ where } } +pub fn draw( + renderer: &mut Renderer, + style: &renderer::Style, + layout: Layout<'_>, + content: &str, + font: Renderer::Font, + size: Option, + color: Option, + horizontal_alignment: alignment::Horizontal, + vertical_alignment: alignment::Vertical, +) where + Renderer: renderer::Text, +{ + let bounds = layout.bounds(); + + let x = match horizontal_alignment { + alignment::Horizontal::Left => bounds.x, + alignment::Horizontal::Center => bounds.center_x(), + alignment::Horizontal::Right => bounds.x + bounds.width, + }; + + let y = match vertical_alignment { + alignment::Vertical::Top => bounds.y, + alignment::Vertical::Center => bounds.center_y(), + alignment::Vertical::Bottom => bounds.y + bounds.height, + }; + + renderer.fill_text(renderer::text::Section { + content, + size: f32::from(size.unwrap_or(renderer.default_size())), + bounds: Rectangle { x, y, ..bounds }, + color: color.unwrap_or(style.text_color), + font, + horizontal_alignment, + vertical_alignment, + }); +} + impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where -- cgit From 47c8f6ceee801bd2896cd075097dcb075ff070d7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 19:07:09 +0700 Subject: Implement `Widget::draw` for `Radio` --- native/src/widget/radio.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 0e1023b5..ebd14517 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -1,14 +1,16 @@ //! Create choices using radio buttons. use std::hash::Hash; +use crate::alignment; use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; +use crate::text; use crate::touch; use crate::{ - Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, - Rectangle, Row, Text, Widget, + Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, + Point, Rectangle, Row, Text, Widget, }; pub use iced_style::radio::{Style, StyleSheet}; @@ -206,6 +208,63 @@ where cursor_position: Point, _viewport: &Rectangle, ) { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + let mut children = layout.children(); + + { + let layout = children.next().unwrap(); + let bounds = layout.bounds(); + + let size = bounds.width; + let dot_size = size / 2.0; + + let style = if is_mouse_over { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style.background, + border_radius: size / 2.0, + border_width: style.border_width, + border_color: style.border_color, + }); + + if self.is_selected { + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + x: bounds.x + dot_size / 2.0, + y: bounds.y + dot_size / 2.0, + width: bounds.width - dot_size, + height: bounds.height - dot_size, + }, + background: Background::Color(style.dot_color), + border_radius: dot_size / 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + } + } + + { + let label_layout = children.next().unwrap(); + + text::draw( + renderer, + style, + label_layout, + &self.label, + self.font, + self.text_size, + self.text_color, + alignment::Horizontal::Left, + alignment::Vertical::Center, + ); + } } fn hash_layout(&self, state: &mut Hasher) { -- cgit From b6ae87ae55301d6c15f56e6c7df077aabe6383de Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 Oct 2021 19:08:13 +0700 Subject: Implement `Widget::mouse_interaction` for `Radio` --- native/src/widget/radio.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index ebd14517..5601a597 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -200,6 +200,19 @@ where event::Status::Ignored } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + if layout.bounds().contains(cursor_position) { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 7c08c6bd138207b862933ee479752a4f1d18c4f2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Oct 2021 18:50:27 +0700 Subject: Remove `Renderer` trait for `Checkbox` --- native/src/widget/checkbox.rs | 55 +++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 33 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index c307d776..c1408d73 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -11,6 +11,8 @@ use crate::{ Rectangle, Row, Text, Widget, }; +pub use iced_style::checkbox::{Style, StyleSheet}; + /// A box that can be checked. /// /// # Example @@ -29,7 +31,7 @@ use crate::{ /// /// ![Checkbox drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Checkbox { +pub struct Checkbox<'a, Message, Renderer: renderer::Text> { is_checked: bool, on_toggle: Box Message>, label: String, @@ -39,12 +41,16 @@ pub struct Checkbox { text_size: Option, font: Renderer::Font, text_color: Option, - style: Renderer::Style, + style_sheet: &'a dyn StyleSheet, } -impl - Checkbox -{ +impl<'a, Message, Renderer: renderer::Text> Checkbox<'a, Message, Renderer> { + /// The default size of a [`Checkbox`]. + const DEFAULT_SIZE: u16 = 20; + + /// The default spacing of a [`Checkbox`]. + const DEFAULT_SPACING: u16 = 15; + /// Creates a new [`Checkbox`]. /// /// It expects: @@ -62,12 +68,12 @@ impl on_toggle: Box::new(f), label: label.into(), width: Length::Shrink, - size: ::DEFAULT_SIZE, - spacing: Renderer::DEFAULT_SPACING, + size: Self::DEFAULT_SIZE, + spacing: Self::DEFAULT_SPACING, text_size: None, font: Renderer::Font::default(), text_color: None, - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -110,16 +116,16 @@ impl } /// Sets the style of the [`Checkbox`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } -impl Widget - for Checkbox +impl<'a, Message, Renderer> Widget + for Checkbox<'a, Message, Renderer> where - Renderer: self::Renderer + renderer::Text, + Renderer: renderer::Text, { fn width(&self) -> Length { self.width @@ -218,31 +224,14 @@ where } } -/// The renderer of a [`Checkbox`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Checkbox`] in your user interface. -/// -/// [renderer]: crate::Renderer -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; - - /// The default size of a [`Checkbox`]. - const DEFAULT_SIZE: u16; - - /// The default spacing of a [`Checkbox`]. - const DEFAULT_SPACING: u16; -} - -impl<'a, Message, Renderer> From> +impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + renderer::Text, + Renderer: 'a + renderer::Text, Message: 'a, { fn from( - checkbox: Checkbox, + checkbox: Checkbox<'a, Message, Renderer>, ) -> Element<'a, Message, Renderer> { Element::new(checkbox) } -- cgit From 1397be38ca2caaf5c49ca51e164a28b63f9e461b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Oct 2021 19:06:22 +0700 Subject: Implement `Widget::draw` for `Checkbox` --- native/src/widget/checkbox.rs | 81 +++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index c1408d73..babd74a5 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -1,10 +1,12 @@ //! Show toggle controls using checkboxes. use std::hash::Hash; +use crate::alignment; use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; +use crate::text; use crate::touch; use crate::{ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, @@ -18,7 +20,7 @@ pub use iced_style::checkbox::{Style, StyleSheet}; /// # Example /// /// ``` -/// # type Checkbox = iced_native::Checkbox; +/// # type Checkbox<'a, Message> = iced_native::Checkbox<'a, Message, iced_native::renderer::Null>; /// # /// pub enum Message { /// CheckboxToggled(bool), @@ -192,28 +194,61 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - // let bounds = layout.bounds(); - // let mut children = layout.children(); - - // let checkbox_layout = children.next().unwrap(); - // let label_layout = children.next().unwrap(); - // let checkbox_bounds = checkbox_layout.bounds(); - - // let label = text::Renderer::draw( - // renderer, - // defaults, - // label_layout.bounds(), - // &self.label, - // self.text_size.unwrap_or(renderer.default_size()), - // self.font, - // self.text_color, - // alignment::Horizontal::Left, - // alignment::Vertical::Center, - // ); - - // let is_mouse_over = bounds.contains(cursor_position); - - // TODO + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + let mut children = layout.children(); + + { + let layout = children.next().unwrap(); + let bounds = layout.bounds(); + + let style = if is_mouse_over { + self.style_sheet.hovered(self.is_checked) + } else { + self.style_sheet.active(self.is_checked) + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style.background, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + + if self.is_checked { + renderer.fill_text(renderer::text::Section { + content: &Renderer::CHECKMARK_ICON.to_string(), + font: Renderer::ICON_FONT, + size: bounds.height * 0.7, + bounds: Rectangle { + x: bounds.center_x(), + y: bounds.center_y(), + ..bounds + }, + color: style.checkmark_color, + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + }); + } + } + + { + let label_layout = children.next().unwrap(); + + text::draw( + renderer, + style, + label_layout, + &self.label, + self.font, + self.text_size, + self.text_color, + alignment::Horizontal::Left, + alignment::Vertical::Center, + ); + } } fn hash_layout(&self, state: &mut Hasher) { -- cgit From e7ae4422312e045a1fbbaa7655d4bf78ca6954a8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Oct 2021 19:07:30 +0700 Subject: Implement `Widget::mouse_interaction` for `Checkbox` --- native/src/widget/checkbox.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index babd74a5..83bc2aa3 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -186,6 +186,19 @@ where event::Status::Ignored } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + if layout.bounds().contains(cursor_position) { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 1afbc98544327b5454b862bec938dc76c4d38fa0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 25 Oct 2021 15:03:57 +0700 Subject: Implement `Widget::draw` for `Image` --- native/src/widget/image.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index b6b8dc1f..b61904f4 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -98,7 +98,7 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { - // TODO + renderer.draw(self.handle.clone(), layout); } fn hash_layout(&self, state: &mut Hasher) { @@ -226,6 +226,9 @@ impl std::fmt::Debug for Data { pub trait Renderer: crate::Renderer { /// Returns the dimensions of an [`Image`] located on the given path. fn dimensions(&self, handle: &Handle) -> (u32, u32); + + // Draws an [`Image`]. + fn draw(&mut self, handle: Handle, layout: Layout<'_>); } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> -- cgit From 41394b4e90a81a43c796c070e706e6aa4d8652bc Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 25 Oct 2021 15:37:28 +0700 Subject: Implement `Widget::draw` for `PaneGrid` --- native/src/widget/pane_grid.rs | 217 ++++++++++++++++++++----------- native/src/widget/pane_grid/content.rs | 79 ++++++----- native/src/widget/pane_grid/title_bar.rs | 77 ++++++----- 3 files changed, 229 insertions(+), 144 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index afecd681..cb386959 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -34,10 +34,12 @@ use crate::overlay; use crate::renderer; use crate::touch; use crate::{ - Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, - Widget, + Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, + Vector, Widget, }; +pub use iced_style::pane_grid::{Line, StyleSheet}; + /// A collection of panes distributed using either vertical or horizontal splits /// to completely fill the space available. /// @@ -88,7 +90,7 @@ use crate::{ /// .on_resize(10, Message::PaneResized); /// ``` #[allow(missing_debug_implementations)] -pub struct PaneGrid<'a, Message, Renderer: self::Renderer> { +pub struct PaneGrid<'a, Message, Renderer> { state: &'a mut state::Internal, elements: Vec<(Pane, Content<'a, Message, Renderer>)>, width: Length, @@ -97,12 +99,12 @@ pub struct PaneGrid<'a, Message, Renderer: self::Renderer> { on_click: Option Message + 'a>>, on_drag: Option Message + 'a>>, on_resize: Option<(u16, Box Message + 'a>)>, - style: ::Style, + style_sheet: &'a dyn StyleSheet, } impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { /// Creates a [`PaneGrid`] with the given [`State`] and view function. /// @@ -129,7 +131,7 @@ where on_click: None, on_drag: None, on_resize: None, - style: Default::default(), + style_sheet: Default::default(), } } @@ -189,18 +191,15 @@ where } /// Sets the style of the [`PaneGrid`]. - pub fn style( - mut self, - style: impl Into<::Style>, - ) -> Self { - self.style = style.into(); + pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { + self.style_sheet = style; self } } impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn click_pane( &mut self, @@ -317,7 +316,7 @@ pub struct ResizeEvent { impl<'a, Message, Renderer> Widget for PaneGrid<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -480,55 +479,136 @@ where cursor_position: Point, viewport: &Rectangle, ) { - // let picked_split = self - // .state - // .picked_split() - // .and_then(|(split, axis)| { - // let bounds = layout.bounds(); - - // let splits = self - // .state - // .split_regions(f32::from(self.spacing), bounds.size()); - - // let (_axis, region, ratio) = splits.get(&split)?; - - // let region = axis.split_line_bounds( - // *region, - // *ratio, - // f32::from(self.spacing), - // ); - - // Some((axis, region + Vector::new(bounds.x, bounds.y), true)) - // }) - // .or_else(|| match self.on_resize { - // Some((leeway, _)) => { - // let bounds = layout.bounds(); - - // let relative_cursor = Point::new( - // cursor_position.x - bounds.x, - // cursor_position.y - bounds.y, - // ); - - // let splits = self - // .state - // .split_regions(f32::from(self.spacing), bounds.size()); - - // let (_split, axis, region) = hovered_split( - // splits.iter(), - // f32::from(self.spacing + leeway), - // relative_cursor, - // )?; - - // Some(( - // axis, - // region + Vector::new(bounds.x, bounds.y), - // false, - // )) - // } - // None => None, - // }); - - // TODO + let picked_pane = self.state.picked_pane(); + + let picked_split = self + .state + .picked_split() + .and_then(|(split, axis)| { + let bounds = layout.bounds(); + + let splits = self + .state + .split_regions(f32::from(self.spacing), bounds.size()); + + let (_axis, region, ratio) = splits.get(&split)?; + + let region = axis.split_line_bounds( + *region, + *ratio, + f32::from(self.spacing), + ); + + Some((axis, region + Vector::new(bounds.x, bounds.y), true)) + }) + .or_else(|| match self.on_resize { + Some((leeway, _)) => { + let bounds = layout.bounds(); + + let relative_cursor = Point::new( + cursor_position.x - bounds.x, + cursor_position.y - bounds.y, + ); + + let splits = self + .state + .split_regions(f32::from(self.spacing), bounds.size()); + + let (_split, axis, region) = hovered_split( + splits.iter(), + f32::from(self.spacing + leeway), + relative_cursor, + )?; + + Some(( + axis, + region + Vector::new(bounds.x, bounds.y), + false, + )) + } + None => None, + }); + + let pane_cursor_position = if picked_pane.is_some() { + // TODO: Remove once cursor availability is encoded in the type + // system + Point::new(-1.0, -1.0) + } else { + cursor_position + }; + + for ((id, pane), layout) in self.elements.iter().zip(layout.children()) + { + match picked_pane { + Some((dragging, origin)) if *id == dragging => { + let bounds = layout.bounds(); + + renderer.with_layer( + Rectangle { + x: cursor_position.x - origin.x, + y: cursor_position.y - origin.y, + width: bounds.width + 0.5, + height: bounds.height + 0.5, + }, + Vector::new(0, 0), + |renderer| { + pane.draw( + renderer, + style, + layout, + pane_cursor_position, + viewport, + ); + }, + ); + } + _ => { + pane.draw( + renderer, + style, + layout, + pane_cursor_position, + viewport, + ); + } + } + } + + if let Some((axis, split_region, is_picked)) = picked_split { + let highlight = if is_picked { + self.style_sheet.picked_split() + } else { + self.style_sheet.hovered_split() + }; + + if let Some(highlight) = highlight { + renderer.fill_rectangle(renderer::Quad { + bounds: match axis { + Axis::Horizontal => Rectangle { + x: split_region.x, + y: (split_region.y + + (split_region.height - highlight.width) + / 2.0) + .round(), + width: split_region.width, + height: highlight.width, + }, + Axis::Vertical => Rectangle { + x: (split_region.x + + (split_region.width - highlight.width) / 2.0) + .round(), + y: split_region.y, + width: highlight.width, + height: split_region.height, + }, + }, + background: highlight.color.into(), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + } + } } fn hash_layout(&self, state: &mut Hasher) { @@ -558,21 +638,10 @@ where } } -/// The renderer of a [`PaneGrid`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`PaneGrid`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// The style supported by this renderer. - type Style: Default; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index 7858c15d..e74e3c84 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -2,7 +2,7 @@ use crate::container; use crate::event::{self, Event}; use crate::layout; use crate::overlay; -use crate::pane_grid::{self, TitleBar}; +use crate::pane_grid::TitleBar; use crate::renderer; use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; @@ -10,22 +10,22 @@ use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; /// /// [`Pane`]: crate::widget::pane_grid::Pane #[allow(missing_debug_implementations)] -pub struct Content<'a, Message, Renderer: pane_grid::Renderer> { +pub struct Content<'a, Message, Renderer> { title_bar: Option>, body: Element<'a, Message, Renderer>, - style: &'a dyn container::StyleSheet, + style_sheet: &'a dyn container::StyleSheet, } impl<'a, Message, Renderer> Content<'a, Message, Renderer> where - Renderer: pane_grid::Renderer, + Renderer: crate::Renderer, { /// Creates a new [`Content`] with the provided body. pub fn new(body: impl Into>) -> Self { Self { title_bar: None, body: body.into(), - style: Default::default(), + style_sheet: Default::default(), } } @@ -39,15 +39,15 @@ where } /// Sets the style of the [`Content`]. - pub fn style(mut self, style: &'a dyn container::StyleSheet) -> Self { - self.style = style; + pub fn style(mut self, style_sheet: &'a dyn container::StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } impl<'a, Message, Renderer> Content<'a, Message, Renderer> where - Renderer: pane_grid::Renderer, + Renderer: crate::Renderer, { /// Draws the [`Content`] with the provided [`Renderer`] and [`Layout`]. /// @@ -60,32 +60,41 @@ where cursor_position: Point, viewport: &Rectangle, ) { - // TODO - // if let Some(title_bar) = &self.title_bar { - // let mut children = layout.children(); - // let title_bar_layout = children.next().unwrap(); - // let body_layout = children.next().unwrap(); - - // renderer.draw_pane( - // defaults, - // layout.bounds(), - // &self.style, - // Some((title_bar, title_bar_layout)), - // (&self.body, body_layout), - // cursor_position, - // viewport, - // ) - // } else { - // renderer.draw_pane( - // defaults, - // layout.bounds(), - // &self.style, - // None, - // (&self.body, layout), - // cursor_position, - // viewport, - // ) - // } + let bounds = layout.bounds(); + + { + let style = self.style_sheet.style(); + + container::draw_background(renderer, &style, bounds); + } + + if let Some(title_bar) = &self.title_bar { + let mut children = layout.children(); + let title_bar_layout = children.next().unwrap(); + let body_layout = children.next().unwrap(); + + let show_controls = bounds.contains(cursor_position); + + title_bar.draw( + renderer, + style, + title_bar_layout, + cursor_position, + viewport, + show_controls, + ); + + self.body.draw( + renderer, + style, + body_layout, + cursor_position, + viewport, + ); + } else { + self.body + .draw(renderer, style, layout, cursor_position, viewport); + } } /// Returns whether the [`Content`] with the given [`Layout`] can be picked @@ -214,7 +223,7 @@ where impl<'a, T, Message, Renderer> From for Content<'a, Message, Renderer> where T: Into>, - Renderer: pane_grid::Renderer, + Renderer: crate::Renderer, { fn from(element: T) -> Self { Self::new(element) diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 22d3a9eb..161eb9bc 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -2,7 +2,6 @@ use crate::container; use crate::event::{self, Event}; use crate::layout; use crate::overlay; -use crate::pane_grid; use crate::renderer; use crate::{ Clipboard, Element, Hasher, Layout, Padding, Point, Rectangle, Size, @@ -12,17 +11,17 @@ use crate::{ /// /// [`Pane`]: crate::widget::pane_grid::Pane #[allow(missing_debug_implementations)] -pub struct TitleBar<'a, Message, Renderer: pane_grid::Renderer> { +pub struct TitleBar<'a, Message, Renderer> { content: Element<'a, Message, Renderer>, controls: Option>, padding: Padding, always_show_controls: bool, - style: &'a dyn container::StyleSheet, + style_sheet: &'a dyn container::StyleSheet, } impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer> where - Renderer: pane_grid::Renderer, + Renderer: crate::Renderer, { /// Creates a new [`TitleBar`] with the given content. pub fn new(content: E) -> Self @@ -34,7 +33,7 @@ where controls: None, padding: Padding::ZERO, always_show_controls: false, - style: Default::default(), + style_sheet: Default::default(), } } @@ -55,7 +54,7 @@ where /// Sets the style of the [`TitleBar`]. pub fn style(mut self, style: &'a dyn container::StyleSheet) -> Self { - self.style = style; + self.style_sheet = style; self } @@ -75,7 +74,7 @@ where impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer> where - Renderer: pane_grid::Renderer, + Renderer: crate::Renderer, { /// Draws the [`TitleBar`] with the provided [`Renderer`] and [`Layout`]. /// @@ -83,39 +82,47 @@ where pub fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + inherited_style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, show_controls: bool, ) { - // let mut children = layout.children(); - // let padded = children.next().unwrap(); - - // let mut children = padded.children(); - // let title_layout = children.next().unwrap(); - - // let controls = if let Some(controls) = &self.controls { - // let controls_layout = children.next().unwrap(); - - // if show_controls || self.always_show_controls { - // Some((controls, controls_layout)) - // } else { - // None - // } - // } else { - // None - // }; - - // renderer.draw_title_bar( - // defaults, - // layout.bounds(), - // &self.style, - // (&self.content, title_layout), - // controls, - // cursor_position, - // viewport, - // ) + let bounds = layout.bounds(); + let style = self.style_sheet.style(); + let inherited_style = renderer::Style { + text_color: style.text_color.unwrap_or(inherited_style.text_color), + }; + + container::draw_background(renderer, &style, bounds); + + let mut children = layout.children(); + let padded = children.next().unwrap(); + + let mut children = padded.children(); + let title_layout = children.next().unwrap(); + + self.content.draw( + renderer, + &inherited_style, + title_layout, + cursor_position, + viewport, + ); + + if let Some(controls) = &self.controls { + let controls_layout = children.next().unwrap(); + + if show_controls || self.always_show_controls { + controls.draw( + renderer, + &inherited_style, + controls_layout, + cursor_position, + viewport, + ); + } + } } /// Returns whether the mouse cursor is over the pick area of the -- cgit From 4a11cbd99445338619dfaf1f327dbc25b2983cb7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 25 Oct 2021 16:16:35 +0700 Subject: Implement `Widget::mouse_interaction` for `PaneGrid` ... and fix rendering of drag interaction in `PaneGrid` by introducing an explicit `with_translation` method to `Renderer` and simplifying the `with_layer` and `Clip` primitive. --- native/src/widget/pane_grid.rs | 57 +++++++++++++++++++++++--------- native/src/widget/pane_grid/content.rs | 36 ++++++++++++++++++++ native/src/widget/pane_grid/title_bar.rs | 30 +++++++++++++++++ native/src/widget/scrollable.rs | 25 ++++++++------ native/src/widget/text_input.rs | 8 ++--- 5 files changed, 126 insertions(+), 30 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index cb386959..5f0e73e4 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -471,6 +471,33 @@ where .fold(event_status, event::Status::merge) } + fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + if self.state.picked_pane().is_some() { + return mouse::Interaction::Grab; + } + + if let Some((_, axis)) = self.state.picked_split() { + return match axis { + Axis::Horizontal => mouse::Interaction::ResizingHorizontally, + Axis::Vertical => mouse::Interaction::ResizingVertically, + }; + } + + self.elements + .iter() + .zip(layout.children()) + .map(|((_pane, content), layout)| { + content.mouse_interaction(layout, viewport, cursor_position) + }) + .max() + .unwrap_or_default() + } + fn draw( &self, renderer: &mut Renderer, @@ -543,22 +570,22 @@ where Some((dragging, origin)) if *id == dragging => { let bounds = layout.bounds(); - renderer.with_layer( - Rectangle { - x: cursor_position.x - origin.x, - y: cursor_position.y - origin.y, - width: bounds.width + 0.5, - height: bounds.height + 0.5, - }, - Vector::new(0, 0), + renderer.with_translation( + cursor_position + - Point::new( + bounds.x + origin.x, + bounds.y + origin.y, + ), |renderer| { - pane.draw( - renderer, - style, - layout, - pane_cursor_position, - viewport, - ); + renderer.with_layer(bounds, |renderer| { + pane.draw( + renderer, + style, + layout, + pane_cursor_position, + viewport, + ); + }); }, ); } diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index e74e3c84..ddc659cc 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -1,6 +1,7 @@ use crate::container; use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::pane_grid::TitleBar; use crate::renderer; @@ -194,6 +195,41 @@ where event_status.merge(body_status) } + pub(crate) fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let mut children = layout.children(); + + let (body_layout, title_bar_interaction) = + if let Some(title_bar) = &self.title_bar { + let title_bar_layout = children.next().unwrap(); + + let is_over_pick_area = title_bar + .is_over_pick_area(title_bar_layout, cursor_position); + + if is_over_pick_area { + return mouse::Interaction::Grab; + } + + let mouse_interaction = title_bar.mouse_interaction( + title_bar_layout, + viewport, + cursor_position, + ); + + (children.next().unwrap(), mouse_interaction) + } else { + (children.next().unwrap(), mouse::Interaction::default()) + }; + + self.body + .mouse_interaction(body_layout, viewport, cursor_position) + .max(title_bar_interaction) + } + pub(crate) fn hash_layout(&self, state: &mut Hasher) { if let Some(title_bar) = &self.title_bar { title_bar.hash_layout(state); diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 161eb9bc..493c74db 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -1,6 +1,7 @@ use crate::container; use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{ @@ -249,6 +250,35 @@ where control_status.merge(title_status) } + pub(crate) fn mouse_interaction( + &self, + layout: Layout<'_>, + viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let mut children = layout.children(); + let padded = children.next().unwrap(); + + let mut children = padded.children(); + let title_layout = children.next().unwrap(); + + let title_interaction = self.content.mouse_interaction( + title_layout, + viewport, + cursor_position, + ); + + if let Some(controls) = &self.controls { + let controls_layout = children.next().unwrap(); + + controls + .mouse_interaction(controls_layout, viewport, cursor_position) + .max(title_interaction) + } else { + title_interaction + } + } + pub(crate) fn overlay( &mut self, layout: Layout<'_>, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 76badbde..563ea370 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -485,15 +485,20 @@ where }; if let Some(scrollbar) = scrollbar { - renderer.with_layer(bounds, Vector::new(0, offset), |renderer| { - self.content.draw( - renderer, - style, - content_layout, - cursor_position, - &Rectangle { - y: bounds.y + offset as f32, - ..bounds + renderer.with_layer(bounds, |renderer| { + renderer.with_translation( + Vector::new(0.0, -(offset as f32)), + |renderer| { + self.content.draw( + renderer, + style, + content_layout, + cursor_position, + &Rectangle { + y: bounds.y + offset as f32, + ..bounds + }, + ); }, ); }); @@ -509,7 +514,7 @@ where let is_scrollbar_visible = style.background.is_some() || style.border_width > 0.0; - renderer.with_layer(bounds, Vector::new(0, 0), |renderer| { + renderer.with_layer(bounds, |renderer| { if is_scrollbar_visible { renderer.fill_rectangle(renderer::Quad { bounds: scrollbar.bounds, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 0a2b19a3..c2950db9 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -751,11 +751,9 @@ where }; if text_width > text_bounds.width { - renderer.with_layer( - text_bounds, - Vector::new(offset as u32, 0), - render, - ); + renderer.with_layer(text_bounds, |renderer| { + renderer.with_translation(Vector::new(-offset, 0.0), render) + }); } else { render(renderer); } -- cgit From fe4dfeafdbc8f427bd351f394d27f606a3843b44 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 15:41:12 +0700 Subject: Wire up style to `PickList` and `overlay::Menu` --- native/src/widget/pick_list.rs | 46 ++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 761cfcc8..81bd41c4 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -6,7 +6,6 @@ use crate::mouse; use crate::overlay; use crate::overlay::menu::{self, Menu}; use crate::renderer; -use crate::text; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, @@ -14,9 +13,11 @@ use crate::{ }; use std::borrow::Cow; +pub use iced_style::pick_list::{Style, StyleSheet}; + /// A widget for selecting a single value from a list of options. #[allow(missing_debug_implementations)] -pub struct PickList<'a, T, Message, Renderer: self::Renderer> +pub struct PickList<'a, T, Message, Renderer: renderer::Text> where [T]: ToOwned>, { @@ -33,7 +34,7 @@ where padding: Padding, text_size: Option, font: Renderer::Font, - style: ::Style, + style_sheet: Box, } /// The local state of a [`PickList`]. @@ -58,12 +59,15 @@ impl Default for State { } } -impl<'a, T: 'a, Message, Renderer: self::Renderer> +impl<'a, T: 'a, Message, Renderer: renderer::Text> PickList<'a, T, Message, Renderer> where T: ToString + Eq, [T]: ToOwned>, { + /// The default padding of a [`PickList`]. + pub const DEFAULT_PADDING: Padding = Padding::new(5); + /// Creates a new [`PickList`] with the given [`State`], a list of options, /// the current selected value, and the message to produce when an option is /// selected. @@ -93,9 +97,9 @@ where selected, width: Length::Shrink, text_size: None, - padding: Renderer::DEFAULT_PADDING, + padding: Self::DEFAULT_PADDING, font: Default::default(), - style: Default::default(), + style_sheet: Default::default(), } } @@ -132,9 +136,9 @@ where /// Sets the style of the [`PickList`]. pub fn style( mut self, - style: impl Into<::Style>, + style_sheet: impl Into>, ) -> Self { - self.style = style.into(); + self.style_sheet = style_sheet.into(); self } } @@ -145,7 +149,7 @@ where T: Clone + ToString + Eq, [T]: ToOwned>, Message: 'static, - Renderer: self::Renderer + 'a, + Renderer: renderer::Text + 'a, { fn width(&self) -> Length { self.width @@ -328,7 +332,6 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - // TODO } fn overlay( @@ -347,7 +350,7 @@ where .width(bounds.width.round() as u16) .padding(self.padding) .font(self.font) - .style(Renderer::menu_style(&self.style)); + .style(self.style_sheet.menu()); if let Some(text_size) = self.text_size { menu = menu.text_size(text_size); @@ -360,31 +363,12 @@ where } } -/// The renderer of a [`PickList`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`PickList`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: renderer::Text + menu::Renderer { - /// The default padding of a [`PickList`]. - const DEFAULT_PADDING: Padding; - - /// The [`PickList`] style supported by this renderer. - type Style: Default; - - /// Returns the style of the [`Menu`] of the [`PickList`]. - fn menu_style( - style: &::Style, - ) -> ::Style; -} - impl<'a, T: 'a, Message, Renderer> Into> for PickList<'a, T, Message, Renderer> where T: Clone + ToString + Eq, [T]: ToOwned>, - Renderer: self::Renderer + 'a, + Renderer: renderer::Text + 'a, Message: 'static, { fn into(self) -> Element<'a, Message, Renderer> { -- cgit From 8740891feb4439e700276a851dcfb660475ed047 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 15:49:05 +0700 Subject: Implement `Widget::draw` for `PickList` --- native/src/widget/pick_list.rs | 62 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 81bd41c4..57375a72 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -1,4 +1,5 @@ //! Display a dropdown list of selectable values. +use crate::alignment; use crate::event::{self, Event}; use crate::keyboard; use crate::layout; @@ -6,6 +7,7 @@ use crate::mouse; use crate::overlay; use crate::overlay::menu::{self, Menu}; use crate::renderer; +use crate::renderer::text; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, @@ -327,11 +329,69 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, _viewport: &Rectangle, ) { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + let is_selected = self.selected.is_some(); + + let style = if is_mouse_over { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style.background, + border_color: style.border_color, + border_width: style.border_width, + border_radius: style.border_radius, + }); + + renderer.fill_text(text::Section { + content: &Renderer::ARROW_DOWN_ICON.to_string(), + font: Renderer::ICON_FONT, + size: bounds.height * style.icon_size, + bounds: Rectangle { + x: bounds.x + bounds.width + - f32::from(self.padding.horizontal()), + y: bounds.center_y(), + ..bounds + }, + color: style.text_color, + horizontal_alignment: alignment::Horizontal::Right, + vertical_alignment: alignment::Vertical::Center, + }); + + if let Some(label) = self + .selected + .as_ref() + .map(ToString::to_string) + .as_ref() + .or_else(|| self.placeholder.as_ref()) + { + renderer.fill_text(text::Section { + content: label, + size: f32::from( + self.text_size.unwrap_or(renderer.default_size()), + ), + font: self.font, + color: is_selected + .then(|| style.text_color) + .unwrap_or(style.placeholder_color), + bounds: Rectangle { + x: bounds.x + f32::from(self.padding.left), + y: bounds.center_y(), + ..bounds + }, + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Center, + }) + } } fn overlay( -- cgit From 5a942ee7ee55c8aa30b48b289661aaec81418f44 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 16:42:32 +0700 Subject: Implement `Widget::mouse_interaction` for `PickList` --- native/src/widget/pick_list.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 57375a72..6fe5feb7 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -326,6 +326,22 @@ where } } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + if is_mouse_over { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 8b1587421822d9a0e7fa1c2224447da7007dbd30 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 17:01:23 +0700 Subject: Implement `Widget::draw` for `image::Viewer` --- native/src/widget/image.rs | 4 ++-- native/src/widget/image/viewer.rs | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index b61904f4..b87c0aab 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -98,7 +98,7 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { - renderer.draw(self.handle.clone(), layout); + renderer.draw(self.handle.clone(), layout.bounds()); } fn hash_layout(&self, state: &mut Hasher) { @@ -228,7 +228,7 @@ pub trait Renderer: crate::Renderer { fn dimensions(&self, handle: &Handle) -> (u32, u32); // Draws an [`Image`]. - fn draw(&mut self, handle: Handle, layout: Layout<'_>); + fn draw(&mut self, handle: Handle, bounds: Rectangle); } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index 63087f5f..3e8430f3 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -284,9 +284,9 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + _cursor_position: Point, _viewport: &Rectangle, ) { let bounds = layout.bounds(); @@ -302,7 +302,19 @@ where image_top_left - self.state.offset(bounds, image_size) }; - let is_mouse_over = bounds.contains(cursor_position); + renderer.with_layer(bounds, |renderer| { + renderer.with_translation(translation, |renderer| { + image::Renderer::draw( + renderer, + self.handle.clone(), + Rectangle { + x: bounds.x, + y: bounds.y, + ..Rectangle::with_size(image_size) + }, + ) + }); + }); } fn hash_layout(&self, state: &mut Hasher) { -- cgit From bc32199e39ee3d42b0d71d9082d56b368e401534 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 17:01:33 +0700 Subject: Implement `Widget::mouse_interaction` for `image::Viewer` --- native/src/widget/image/viewer.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index 3e8430f3..d9eccfad 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -281,6 +281,24 @@ where } } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + if self.state.is_cursor_grabbed() { + mouse::Interaction::Grabbing + } else if is_mouse_over { + mouse::Interaction::Grab + } else { + mouse::Interaction::Idle + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From e42e1e2f57ddb455ceff0017e215ddacca978d37 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 17:36:36 +0700 Subject: Implement `Widget::draw` for `ProgressBar` --- native/src/widget/progress_bar.rs | 100 +++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 40 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 98dd9989..9e857226 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -1,17 +1,19 @@ //! Provide progress feedback to your users. use crate::layout; use crate::renderer; -use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; +use crate::{ + Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, +}; use std::{hash::Hash, ops::RangeInclusive}; +pub use iced_style::progress_bar::{Style, StyleSheet}; + /// A bar that displays progress. /// /// # Example /// ``` -/// # use iced_native::renderer::Null; -/// # -/// # pub type ProgressBar = iced_native::ProgressBar; +/// # use iced_native::ProgressBar; /// let value = 50.0; /// /// ProgressBar::new(0.0..=100.0, value); @@ -19,15 +21,18 @@ use std::{hash::Hash, ops::RangeInclusive}; /// /// ![Progress bar drawn with `iced_wgpu`](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png) #[allow(missing_debug_implementations)] -pub struct ProgressBar { +pub struct ProgressBar { range: RangeInclusive, value: f32, width: Length, height: Option, - style: Renderer::Style, + style_sheet: Box, } -impl ProgressBar { +impl ProgressBar { + /// The default height of a [`ProgressBar`]. + pub const DEFAULT_HEIGHT: u16 = 30; + /// Creates a new [`ProgressBar`]. /// /// It expects: @@ -39,7 +44,7 @@ impl ProgressBar { range, width: Length::Fill, height: None, - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -56,23 +61,25 @@ impl ProgressBar { } /// Sets the style of the [`ProgressBar`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -impl Widget for ProgressBar +impl Widget for ProgressBar where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width } fn height(&self) -> Length { - self.height - .unwrap_or(Length::Units(Renderer::DEFAULT_HEIGHT)) + self.height.unwrap_or(Length::Units(Self::DEFAULT_HEIGHT)) } fn layout( @@ -80,10 +87,9 @@ where _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let limits = limits.width(self.width).height( - self.height - .unwrap_or(Length::Units(Renderer::DEFAULT_HEIGHT)), - ); + let limits = limits + .width(self.width) + .height(self.height.unwrap_or(Length::Units(Self::DEFAULT_HEIGHT))); let size = limits.resolve(Size::ZERO); @@ -93,12 +99,43 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { - // TODO + let bounds = layout.bounds(); + let (range_start, range_end) = self.range.clone().into_inner(); + + let active_progress_width = if range_start >= range_end { + 0.0 + } else { + bounds.width * (self.value - range_start) + / (range_end - range_start) + }; + + let style = self.style_sheet.style(); + + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { ..bounds }, + background: style.background, + border_radius: style.border_radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + + if active_progress_width > 0.0 { + renderer.fill_rectangle(renderer::Quad { + bounds: Rectangle { + width: active_progress_width, + ..bounds + }, + background: style.bar, + border_radius: style.border_radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); + } } fn hash_layout(&self, state: &mut Hasher) { @@ -110,29 +147,12 @@ where } } -/// The renderer of a [`ProgressBar`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`ProgressBar`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; - - /// The default height of a [`ProgressBar`]. - const DEFAULT_HEIGHT: u16; -} - -impl<'a, Message, Renderer> From> - for Element<'a, Message, Renderer> +impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { - fn from( - progress_bar: ProgressBar, - ) -> Element<'a, Message, Renderer> { + fn from(progress_bar: ProgressBar) -> Element<'a, Message, Renderer> { Element::new(progress_bar) } } -- cgit From d127dbd08ec314e6a2c65961134bdc7b28a1e4aa Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 17:55:07 +0700 Subject: Fix scrollbar clipping in `Scrollable` draw logic --- native/src/widget/scrollable.rs | 57 +++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 563ea370..4b514818 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -514,32 +514,39 @@ where let is_scrollbar_visible = style.background.is_some() || style.border_width > 0.0; - renderer.with_layer(bounds, |renderer| { - if is_scrollbar_visible { - renderer.fill_rectangle(renderer::Quad { - bounds: scrollbar.bounds, - background: style - .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); - } + renderer.with_layer( + Rectangle { + width: bounds.width + 2.0, + height: bounds.height + 2.0, + ..bounds + }, + |renderer| { + if is_scrollbar_visible { + renderer.fill_rectangle(renderer::Quad { + bounds: scrollbar.bounds, + background: style.background.unwrap_or( + Background::Color(Color::TRANSPARENT), + ), + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + } - if is_mouse_over - || self.state.is_scroller_grabbed() - || is_scrollbar_visible - { - renderer.fill_rectangle(renderer::Quad { - bounds: scrollbar.scroller.bounds, - background: Background::Color(style.scroller.color), - border_radius: style.scroller.border_radius, - border_width: style.scroller.border_width, - border_color: style.scroller.border_color, - }); - } - }); + if is_mouse_over + || self.state.is_scroller_grabbed() + || is_scrollbar_visible + { + renderer.fill_rectangle(renderer::Quad { + bounds: scrollbar.scroller.bounds, + background: Background::Color(style.scroller.color), + border_radius: style.scroller.border_radius, + border_width: style.scroller.border_width, + border_color: style.scroller.border_color, + }); + } + }, + ); } else { self.content.draw( renderer, -- cgit From f6257973926233e7bb18ae3b4dee4385bfc6ab61 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 18:03:24 +0700 Subject: Implement `Widget::draw` for `Rule` --- native/src/widget/rule.rs | 87 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 24 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 24c4a51a..f0d50006 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -1,27 +1,32 @@ //! Display a horizontal or vertical rule for dividing content. use crate::layout; use crate::renderer; -use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; +use crate::{ + Background, Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, + Widget, +}; use std::hash::Hash; +pub use iced_style::rule::{FillMode, Style, StyleSheet}; + /// Display a horizontal or vertical rule for dividing content. -#[derive(Debug, Copy, Clone)] -pub struct Rule { +#[allow(missing_debug_implementations)] +pub struct Rule { width: Length, height: Length, - style: Renderer::Style, is_horizontal: bool, + style_sheet: Box, } -impl Rule { +impl Rule { /// Creates a horizontal [`Rule`] for dividing content by the given vertical spacing. pub fn horizontal(spacing: u16) -> Self { Rule { width: Length::Fill, height: Length::from(Length::Units(spacing)), - style: Renderer::Style::default(), is_horizontal: true, + style_sheet: Default::default(), } } @@ -30,21 +35,24 @@ impl Rule { Rule { width: Length::from(Length::Units(spacing)), height: Length::Fill, - style: Renderer::Style::default(), is_horizontal: false, + style_sheet: Default::default(), } } /// Sets the style of the [`Rule`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -impl Widget for Rule +impl Widget for Rule where - Renderer: self::Renderer, + Renderer: crate::Renderer, { fn width(&self) -> Length { self.width @@ -67,13 +75,51 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // renderer.draw(layout.bounds(), &self.style, self.is_horizontal) + let bounds = layout.bounds(); + let style = self.style_sheet.style(); + + let bounds = if self.is_horizontal { + let line_y = (bounds.y + (bounds.height / 2.0) + - (style.width as f32 / 2.0)) + .round(); + + let (offset, line_width) = style.fill_mode.fill(bounds.width); + let line_x = bounds.x + offset; + + Rectangle { + x: line_x, + y: line_y, + width: line_width, + height: style.width as f32, + } + } else { + let line_x = (bounds.x + (bounds.width / 2.0) + - (style.width as f32 / 2.0)) + .round(); + + let (offset, line_height) = style.fill_mode.fill(bounds.height); + let line_y = bounds.y + offset; + + Rectangle { + x: line_x, + y: line_y, + width: style.width as f32, + height: line_height, + } + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: Background::Color(style.color), + border_radius: style.radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }); } fn hash_layout(&self, state: &mut Hasher) { @@ -85,19 +131,12 @@ where } } -/// The renderer of a [`Rule`]. -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; -} - -impl<'a, Message, Renderer> From> - for Element<'a, Message, Renderer> +impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + crate::Renderer, Message: 'a, { - fn from(rule: Rule) -> Element<'a, Message, Renderer> { + fn from(rule: Rule) -> Element<'a, Message, Renderer> { Element::new(rule) } } -- cgit From 1c2792c0a0dc565f9dd9183ca8948331ec467590 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 18:17:47 +0700 Subject: Implement `Widget::draw` for `Toggler` --- native/src/widget/toggler.rs | 144 +++++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 53 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 46a9850b..25ed95ca 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -6,11 +6,14 @@ use crate::event; use crate::layout; use crate::mouse; use crate::renderer; +use crate::widget::text; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, Rectangle, Row, Text, Widget, }; +pub use iced_style::toggler::{Style, StyleSheet}; + /// A toggler widget /// /// # Example @@ -27,7 +30,7 @@ use crate::{ /// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b)); /// ``` #[allow(missing_debug_implementations)] -pub struct Toggler { +pub struct Toggler { is_active: bool, on_toggle: Box Message>, label: Option, @@ -37,12 +40,13 @@ pub struct Toggler { text_alignment: alignment::Horizontal, spacing: u16, font: Renderer::Font, - style: Renderer::Style, + style_sheet: Box, } -impl - Toggler -{ +impl Toggler { + /// The default size of a [`Toggler`]. + pub const DEFAULT_SIZE: u16 = 20; + /// Creates a new [`Toggler`]. /// /// It expects: @@ -64,12 +68,12 @@ impl on_toggle: Box::new(f), label: label.into(), width: Length::Fill, - size: ::DEFAULT_SIZE, + size: Self::DEFAULT_SIZE, text_size: None, text_alignment: alignment::Horizontal::Left, spacing: 0, font: Renderer::Font::default(), - style: Renderer::Style::default(), + style_sheet: Default::default(), } } @@ -110,15 +114,18 @@ impl } /// Sets the style of the [`Toggler`]. - pub fn style(mut self, style: impl Into) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } impl Widget for Toggler where - Renderer: self::Renderer + renderer::Text, + Renderer: renderer::Text, { fn width(&self) -> Length { self.width @@ -190,34 +197,79 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // let bounds = layout.bounds(); - // let mut children = layout.children(); - - // let label = match &self.label { - // Some(label) => { - // let label_layout = children.next().unwrap(); - - // Some(text::Renderer::draw( - // renderer, - // defaults, - // label_layout.bounds(), - // &label, - // self.text_size.unwrap_or(renderer.default_size()), - // self.font, - // None, - // self.text_alignment, - // alignment::Vertical::Center, - // )) - // } - - // None => None, - // }; - - // let toggler_layout = children.next().unwrap(); - // let toggler_bounds = toggler_layout.bounds(); - - // let is_mouse_over = bounds.contains(cursor_position); + /// Makes sure that the border radius of the toggler looks good at every size. + const BORDER_RADIUS_RATIO: f32 = 32.0 / 13.0; + + /// The space ratio between the background Quad and the Toggler bounds, and + /// between the background Quad and foreground Quad. + const SPACE_RATIO: f32 = 0.05; + + let mut children = layout.children(); + + if let Some(label) = &self.label { + let label_layout = children.next().unwrap(); + + text::draw( + renderer, + style, + label_layout, + &label, + self.font, + self.text_size, + None, + self.text_alignment, + alignment::Vertical::Center, + ); + } + + let toggler_layout = children.next().unwrap(); + let bounds = toggler_layout.bounds(); + + let is_mouse_over = bounds.contains(cursor_position); + + let style = if is_mouse_over { + self.style_sheet.hovered(self.is_active) + } else { + self.style_sheet.active(self.is_active) + }; + + let border_radius = bounds.height as f32 / BORDER_RADIUS_RATIO; + let space = SPACE_RATIO * bounds.height as f32; + + let toggler_background_bounds = Rectangle { + x: bounds.x + space, + y: bounds.y + space, + width: bounds.width - (2.0 * space), + height: bounds.height - (2.0 * space), + }; + + renderer.fill_rectangle(renderer::Quad { + bounds: toggler_background_bounds, + background: style.background.into(), + border_radius, + border_width: 1.0, + border_color: style.background_border.unwrap_or(style.background), + }); + + let toggler_foreground_bounds = Rectangle { + x: bounds.x + + if self.is_active { + bounds.width - 2.0 * space - (bounds.height - (4.0 * space)) + } else { + 2.0 * space + }, + y: bounds.y + (2.0 * space), + width: bounds.height - (4.0 * space), + height: bounds.height - (4.0 * space), + }; + + renderer.fill_rectangle(renderer::Quad { + bounds: toggler_foreground_bounds, + background: style.foreground.into(), + border_radius, + border_width: 1.0, + border_color: style.foreground_border.unwrap_or(style.foreground), + }); } fn hash_layout(&self, state: &mut Hasher) { @@ -228,24 +280,10 @@ where } } -/// The renderer of a [`Toggler`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Toggler`] in your user interface. -/// -/// [renderer]: ../../renderer/index.html -pub trait Renderer: crate::Renderer { - /// The style supported by this renderer. - type Style: Default; - - /// The default size of a [`Toggler`]. - const DEFAULT_SIZE: u16; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + renderer::Text, + Renderer: 'a + renderer::Text, Message: 'a, { fn from( -- cgit From 5cd744f9862c62ca441d4a4b3962d91e4360afbf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 18:19:19 +0700 Subject: Implement `Widget::mouse_interaction` for `Toggler` --- native/src/widget/toggler.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'native/src/widget') diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 25ed95ca..a11d0307 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -189,6 +189,19 @@ where } } + fn mouse_interaction( + &self, + layout: Layout<'_>, + _viewport: &Rectangle, + cursor_position: Point, + ) -> mouse::Interaction { + if layout.bounds().contains(cursor_position) { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 0f8d6e8703d3cd604da7b702aabd184a5e4e8a63 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 20:18:57 +0700 Subject: Fix unused variables in `Widget::draw` for `Space` --- native/src/widget/space.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index 1bf8cd68..3373f3b7 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -61,9 +61,9 @@ where fn draw( &self, - renderer: &mut Renderer, - style: &renderer::Style, - layout: Layout<'_>, + _renderer: &mut Renderer, + _style: &renderer::Style, + _layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { -- cgit From 5fee1e33d4a873c5e37e6c158257bcf54fd17452 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 20:30:25 +0700 Subject: Implement `Widget::draw` for `Tooltip` --- native/src/widget/tooltip.rs | 154 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 31 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index c2bc8af0..a00158f6 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -8,23 +8,29 @@ use crate::layout; use crate::renderer; use crate::widget::container; use crate::widget::text::Text; -use crate::{Clipboard, Element, Event, Hasher, Layout, Length, Point, Widget}; +use crate::{ + Clipboard, Element, Event, Hasher, Layout, Length, Padding, Point, Size, + Vector, Widget, +}; /// An element to display a widget over another. #[allow(missing_debug_implementations)] -pub struct Tooltip<'a, Message, Renderer: self::Renderer> { +pub struct Tooltip<'a, Message, Renderer: renderer::Text> { content: Element<'a, Message, Renderer>, tooltip: Text, position: Position, - style: &'a dyn container::StyleSheet, + style_sheet: &'a dyn container::StyleSheet, gap: u16, padding: u16, } impl<'a, Message, Renderer> Tooltip<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: renderer::Text, { + /// The default padding of a [`Tooltip`] drawn by this renderer. + const DEFAULT_PADDING: u16 = 5; + /// Creates an empty [`Tooltip`]. /// /// [`Tooltip`]: struct.Tooltip.html @@ -37,9 +43,9 @@ where content: content.into(), tooltip: Text::new(tooltip.to_string()), position, - style: Default::default(), + style_sheet: Default::default(), gap: 0, - padding: Renderer::DEFAULT_PADDING, + padding: Self::DEFAULT_PADDING, } } @@ -70,11 +76,8 @@ where } /// Sets the style of the [`Tooltip`]. - pub fn style<'b>(mut self, style: &'b dyn container::StyleSheet) -> Self - where - 'b: 'a, - { - self.style = style; + pub fn style(mut self, style_sheet: &'a dyn container::StyleSheet) -> Self { + self.style_sheet = style_sheet; self } } @@ -97,7 +100,7 @@ pub enum Position { impl<'a, Message, Renderer> Widget for Tooltip<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: renderer::Text, { fn width(&self) -> Length { self.content.width() @@ -136,13 +139,114 @@ where fn draw( &self, - _renderer: &mut Renderer, - style: &renderer::Style, - _layout: Layout<'_>, - _cursor_position: Point, - _viewport: &Rectangle, + renderer: &mut Renderer, + inherited_style: &renderer::Style, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, ) { - // TODO + self.content.draw( + renderer, + inherited_style, + layout, + cursor_position, + viewport, + ); + + let bounds = layout.bounds(); + + if bounds.contains(cursor_position) { + let gap = f32::from(self.gap); + let style = self.style_sheet.style(); + + let defaults = renderer::Style { + text_color: style + .text_color + .unwrap_or(inherited_style.text_color), + }; + + let text_layout = Widget::<(), Renderer>::layout( + &self.tooltip, + renderer, + &layout::Limits::new(Size::ZERO, viewport.size()) + .pad(Padding::new(self.padding)), + ); + + let padding = f32::from(self.padding); + let text_bounds = text_layout.bounds(); + let x_center = bounds.x + (bounds.width - text_bounds.width) / 2.0; + let y_center = + bounds.y + (bounds.height - text_bounds.height) / 2.0; + + let mut tooltip_bounds = { + let offset = match self.position { + Position::Top => Vector::new( + x_center, + bounds.y - text_bounds.height - gap - padding, + ), + Position::Bottom => Vector::new( + x_center, + bounds.y + bounds.height + gap + padding, + ), + Position::Left => Vector::new( + bounds.x - text_bounds.width - gap - padding, + y_center, + ), + Position::Right => Vector::new( + bounds.x + bounds.width + gap + padding, + y_center, + ), + Position::FollowCursor => Vector::new( + cursor_position.x, + cursor_position.y - text_bounds.height, + ), + }; + + Rectangle { + x: offset.x - padding, + y: offset.y - padding, + width: text_bounds.width + padding * 2.0, + height: text_bounds.height + padding * 2.0, + } + }; + + if tooltip_bounds.x < viewport.x { + tooltip_bounds.x = viewport.x; + } else if viewport.x + viewport.width + < tooltip_bounds.x + tooltip_bounds.width + { + tooltip_bounds.x = + viewport.x + viewport.width - tooltip_bounds.width; + } + + if tooltip_bounds.y < viewport.y { + tooltip_bounds.y = viewport.y; + } else if viewport.y + viewport.height + < tooltip_bounds.y + tooltip_bounds.height + { + tooltip_bounds.y = + viewport.y + viewport.height - tooltip_bounds.height; + } + + renderer.with_layer(*viewport, |renderer| { + container::draw_background(renderer, &style, tooltip_bounds); + + Widget::<(), Renderer>::draw( + &self.tooltip, + renderer, + &defaults, + Layout::with_offset( + Vector::new( + tooltip_bounds.x + padding, + tooltip_bounds.y + padding, + ), + &text_layout, + ), + cursor_position, + viewport, + ); + }); + } } fn hash_layout(&self, state: &mut Hasher) { @@ -153,22 +257,10 @@ where } } -/// The renderer of a [`Tooltip`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Tooltip`] in your user interface. -/// -/// [`Tooltip`]: struct.Tooltip.html -/// [renderer]: ../../renderer/index.html -pub trait Renderer: renderer::Text { - /// The default padding of a [`Tooltip`] drawn by this renderer. - const DEFAULT_PADDING: u16; -} - impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer, + Renderer: 'a + renderer::Text, Message: 'a, { fn from( -- cgit From e6156fb0c53d78ae75a1d85d4bfd81f6b7e8817e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Oct 2021 22:13:26 +0700 Subject: Implement `Widget::draw` for `Svg` --- native/src/widget/svg.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index cce560cb..785b8054 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -89,13 +89,12 @@ where fn draw( &self, renderer: &mut Renderer, - style: &renderer::Style, + _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { - // TODO - // renderer.draw(self.handle.clone(), layout) + renderer.draw(self.handle.clone(), layout.bounds()) } fn hash_layout(&self, state: &mut Hasher) { @@ -187,6 +186,9 @@ impl std::fmt::Debug for Data { pub trait Renderer: crate::Renderer { /// Returns the default dimensions of an [`Svg`] for the given [`Handle`]. fn dimensions(&self, handle: &Handle) -> (u32, u32); + + // Draws an [`Svg`]. + fn draw(&mut self, handle: Handle, bounds: Rectangle); } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> -- cgit From 0aafcde0ef1533c9eeba0379de8c0082e30c7504 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 15:35:12 +0700 Subject: Remove `widget` module re-exports in `iced_native` --- native/src/widget/button.rs | 8 ++++---- native/src/widget/checkbox.rs | 7 ++++--- native/src/widget/image.rs | 2 +- native/src/widget/image/viewer.rs | 2 +- native/src/widget/pane_grid.rs | 4 ++-- native/src/widget/pane_grid/configuration.rs | 2 +- native/src/widget/pane_grid/content.rs | 4 ++-- native/src/widget/pane_grid/node.rs | 6 ++---- native/src/widget/pane_grid/state.rs | 6 +++--- native/src/widget/pane_grid/title_bar.rs | 2 +- native/src/widget/progress_bar.rs | 2 +- native/src/widget/radio.rs | 7 ++++--- native/src/widget/scrollable.rs | 5 +++-- native/src/widget/slider.rs | 2 +- native/src/widget/text.rs | 2 +- native/src/widget/text_input.rs | 5 +++-- native/src/widget/text_input/editor.rs | 2 +- native/src/widget/toggler.rs | 5 +++-- 18 files changed, 38 insertions(+), 35 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index a654cf12..a577fe84 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -19,10 +19,10 @@ pub use iced_style::button::{Style, StyleSheet}; /// A generic widget that produces a message when pressed. /// /// ``` -/// # use iced_native::{button, Text}; +/// # use iced_native::widget::{button, Text}; /// # /// # type Button<'a, Message> = -/// # iced_native::Button<'a, Message, iced_native::renderer::Null>; +/// # iced_native::widget::Button<'a, Message, iced_native::renderer::Null>; /// # /// #[derive(Clone)] /// enum Message { @@ -38,10 +38,10 @@ pub use iced_style::button::{Style, StyleSheet}; /// be disabled: /// /// ``` -/// # use iced_native::{button, Text}; +/// # use iced_native::widget::{button, Text}; /// # /// # type Button<'a, Message> = -/// # iced_native::Button<'a, Message, iced_native::renderer::Null>; +/// # iced_native::widget::Button<'a, Message, iced_native::renderer::Null>; /// # /// #[derive(Clone)] /// enum Message { diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 83bc2aa3..b81a444e 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -6,11 +6,12 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; -use crate::text; use crate::touch; +use crate::widget::text; +use crate::widget::{Row, Text}; use crate::{ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, - Rectangle, Row, Text, Widget, + Rectangle, Widget, }; pub use iced_style::checkbox::{Style, StyleSheet}; @@ -20,7 +21,7 @@ pub use iced_style::checkbox::{Style, StyleSheet}; /// # Example /// /// ``` -/// # type Checkbox<'a, Message> = iced_native::Checkbox<'a, Message, iced_native::renderer::Null>; +/// # type Checkbox<'a, Message> = iced_native::widget::Checkbox<'a, Message, iced_native::renderer::Null>; /// # /// pub enum Message { /// CheckboxToggled(bool), diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index b87c0aab..d23d393a 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -17,7 +17,7 @@ use std::{ /// # Example /// /// ``` -/// # use iced_native::Image; +/// # use iced_native::widget::Image; /// # /// let image = Image::new("resources/ferris.png"); /// ``` diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index d9eccfad..d3c794a7 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -1,9 +1,9 @@ //! Zoom and pan on an image. use crate::event::{self, Event}; -use crate::image; use crate::layout; use crate::mouse; use crate::renderer; +use crate::widget::image; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 5f0e73e4..22c18c05 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -62,10 +62,10 @@ pub use iced_style::pane_grid::{Line, StyleSheet}; /// ## Example /// /// ``` -/// # use iced_native::{pane_grid, Text}; +/// # use iced_native::widget::{pane_grid, Text}; /// # /// # type PaneGrid<'a, Message> = -/// # iced_native::PaneGrid<'a, Message, iced_native::renderer::Null>; +/// # iced_native::widget::PaneGrid<'a, Message, iced_native::renderer::Null>; /// # /// enum PaneState { /// SomePane, diff --git a/native/src/widget/pane_grid/configuration.rs b/native/src/widget/pane_grid/configuration.rs index 4c43826e..4c52bad4 100644 --- a/native/src/widget/pane_grid/configuration.rs +++ b/native/src/widget/pane_grid/configuration.rs @@ -1,4 +1,4 @@ -use crate::pane_grid::Axis; +use crate::widget::pane_grid::Axis; /// The arrangement of a [`PaneGrid`]. /// diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index ddc659cc..83d96917 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -1,10 +1,10 @@ -use crate::container; use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; -use crate::pane_grid::TitleBar; use crate::renderer; +use crate::widget::container; +use crate::widget::pane_grid::TitleBar; use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; /// The content of a [`Pane`]. diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index 84714e00..af6573a0 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -1,7 +1,5 @@ -use crate::{ - pane_grid::{Axis, Pane, Split}, - Rectangle, Size, -}; +use crate::widget::pane_grid::{Axis, Pane, Split}; +use crate::{Rectangle, Size}; use std::collections::BTreeMap; diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index fb96f89f..bcc724a8 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -1,7 +1,7 @@ -use crate::{ - pane_grid::{Axis, Configuration, Direction, Node, Pane, Split}, - Hasher, Point, Rectangle, Size, +use crate::widget::pane_grid::{ + Axis, Configuration, Direction, Node, Pane, Split, }; +use crate::{Hasher, Point, Rectangle, Size}; use std::collections::{BTreeMap, HashMap}; diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 493c74db..2d66ba6c 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -1,9 +1,9 @@ -use crate::container; use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::overlay; use crate::renderer; +use crate::widget::container; use crate::{ Clipboard, Element, Hasher, Layout, Padding, Point, Rectangle, Size, }; diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 9e857226..48bf485e 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -13,7 +13,7 @@ pub use iced_style::progress_bar::{Style, StyleSheet}; /// /// # Example /// ``` -/// # use iced_native::ProgressBar; +/// # use iced_native::widget::ProgressBar; /// let value = 50.0; /// /// ProgressBar::new(0.0..=100.0, value); diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 5601a597..91de8be5 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -6,11 +6,12 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; -use crate::text; use crate::touch; +use crate::widget::text; +use crate::widget::{Row, Text}; use crate::{ Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, - Point, Rectangle, Row, Text, Widget, + Point, Rectangle, Widget, }; pub use iced_style::radio::{Style, StyleSheet}; @@ -20,7 +21,7 @@ pub use iced_style::radio::{Style, StyleSheet}; /// # Example /// ``` /// # type Radio<'a, Message> = -/// # iced_native::Radio<'a, Message, iced_native::renderer::Null>; +/// # iced_native::widget::Radio<'a, Message, iced_native::renderer::Null>; /// # /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] /// pub enum Choice { diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 4b514818..781fe73e 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -5,9 +5,10 @@ use crate::mouse; use crate::overlay; use crate::renderer; use crate::touch; +use crate::widget::Column; use crate::{ - Alignment, Background, Clipboard, Color, Column, Element, Hasher, Layout, - Length, Padding, Point, Rectangle, Size, Vector, Widget, + Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, + Padding, Point, Rectangle, Size, Vector, Widget, }; use std::{f32, hash::Hash, u32}; diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 60124160..977a5240 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -26,7 +26,7 @@ pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet}; /// /// # Example /// ``` -/// # use iced_native::slider::{self, Slider}; +/// # use iced_native::widget::slider::{self, Slider}; /// # /// #[derive(Clone)] /// pub enum Message { diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 2432dbc8..563ab8c4 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -15,7 +15,7 @@ use std::hash::Hash; /// # Example /// /// ``` -/// # type Text = iced_native::Text; +/// # type Text = iced_native::widget::Text; /// # /// Text::new("I <3 iced!") /// .color([0.0, 0.0, 1.0]) diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index c2950db9..5d67ddfe 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -31,9 +31,10 @@ pub use iced_style::text_input::{Style, StyleSheet}; /// /// # Example /// ``` -/// # use iced_native::{text_input, renderer::Null}; +/// # use iced_native::renderer::Null; +/// # use iced_native::widget::text_input; /// # -/// # pub type TextInput<'a, Message> = iced_native::TextInput<'a, Message, Null>; +/// # pub type TextInput<'a, Message> = iced_native::widget::TextInput<'a, Message, Null>; /// #[derive(Debug, Clone)] /// enum Message { /// TextInputChanged(String), diff --git a/native/src/widget/text_input/editor.rs b/native/src/widget/text_input/editor.rs index 0b50a382..bac530e1 100644 --- a/native/src/widget/text_input/editor.rs +++ b/native/src/widget/text_input/editor.rs @@ -1,4 +1,4 @@ -use crate::text_input::{Cursor, Value}; +use crate::widget::text_input::{Cursor, Value}; pub struct Editor<'a> { value: &'a mut Value, diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index a11d0307..20cfea74 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -7,9 +7,10 @@ use crate::layout; use crate::mouse; use crate::renderer; use crate::widget::text; +use crate::widget::{Row, Text}; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Rectangle, Row, Text, Widget, + Rectangle, Widget, }; pub use iced_style::toggler::{Style, StyleSheet}; @@ -19,7 +20,7 @@ pub use iced_style::toggler::{Style, StyleSheet}; /// # Example /// /// ``` -/// # type Toggler = iced_native::Toggler; +/// # type Toggler = iced_native::widget::Toggler; /// # /// pub enum Message { /// TogglerToggled(bool), -- cgit From b3a01973c6c726e6539be959659f4306ef3234c6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 16:13:03 +0700 Subject: Introduce first-class `text` module in `iced_native` --- native/src/widget/checkbox.rs | 16 ++++++++-------- native/src/widget/pick_list.rs | 14 +++++++------- native/src/widget/radio.rs | 14 +++++++------- native/src/widget/text.rs | 17 ++++++++--------- native/src/widget/text_input.rs | 19 ++++++++++--------- native/src/widget/toggler.rs | 12 ++++++------ native/src/widget/tooltip.rs | 9 +++++---- 7 files changed, 51 insertions(+), 50 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index b81a444e..624e01d6 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -6,9 +6,9 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; +use crate::text; use crate::touch; -use crate::widget::text; -use crate::widget::{Row, Text}; +use crate::widget::{self, Row, Text}; use crate::{ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Widget, @@ -34,7 +34,7 @@ pub use iced_style::checkbox::{Style, StyleSheet}; /// /// ![Checkbox drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Checkbox<'a, Message, Renderer: renderer::Text> { +pub struct Checkbox<'a, Message, Renderer: text::Renderer> { is_checked: bool, on_toggle: Box Message>, label: String, @@ -47,7 +47,7 @@ pub struct Checkbox<'a, Message, Renderer: renderer::Text> { style_sheet: &'a dyn StyleSheet, } -impl<'a, Message, Renderer: renderer::Text> Checkbox<'a, Message, Renderer> { +impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> { /// The default size of a [`Checkbox`]. const DEFAULT_SIZE: u16 = 20; @@ -128,7 +128,7 @@ impl<'a, Message, Renderer: renderer::Text> Checkbox<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget for Checkbox<'a, Message, Renderer> where - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.width @@ -232,7 +232,7 @@ where }); if self.is_checked { - renderer.fill_text(renderer::text::Section { + renderer.fill_text(text::Text { content: &Renderer::CHECKMARK_ICON.to_string(), font: Renderer::ICON_FONT, size: bounds.height * 0.7, @@ -251,7 +251,7 @@ where { let label_layout = children.next().unwrap(); - text::draw( + widget::text::draw( renderer, style, label_layout, @@ -276,7 +276,7 @@ where impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + renderer::Text, + Renderer: 'a + text::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 6fe5feb7..3a393e14 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -7,7 +7,7 @@ use crate::mouse; use crate::overlay; use crate::overlay::menu::{self, Menu}; use crate::renderer; -use crate::renderer::text; +use crate::text::{self, Text}; use crate::touch; use crate::{ Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, @@ -19,7 +19,7 @@ pub use iced_style::pick_list::{Style, StyleSheet}; /// A widget for selecting a single value from a list of options. #[allow(missing_debug_implementations)] -pub struct PickList<'a, T, Message, Renderer: renderer::Text> +pub struct PickList<'a, T, Message, Renderer: text::Renderer> where [T]: ToOwned>, { @@ -61,7 +61,7 @@ impl Default for State { } } -impl<'a, T: 'a, Message, Renderer: renderer::Text> +impl<'a, T: 'a, Message, Renderer: text::Renderer> PickList<'a, T, Message, Renderer> where T: ToString + Eq, @@ -151,7 +151,7 @@ where T: Clone + ToString + Eq, [T]: ToOwned>, Message: 'static, - Renderer: renderer::Text + 'a, + Renderer: text::Renderer + 'a, { fn width(&self) -> Length { self.width @@ -368,7 +368,7 @@ where border_radius: style.border_radius, }); - renderer.fill_text(text::Section { + renderer.fill_text(Text { content: &Renderer::ARROW_DOWN_ICON.to_string(), font: Renderer::ICON_FONT, size: bounds.height * style.icon_size, @@ -390,7 +390,7 @@ where .as_ref() .or_else(|| self.placeholder.as_ref()) { - renderer.fill_text(text::Section { + renderer.fill_text(Text { content: label, size: f32::from( self.text_size.unwrap_or(renderer.default_size()), @@ -444,7 +444,7 @@ impl<'a, T: 'a, Message, Renderer> Into> where T: Clone + ToString + Eq, [T]: ToOwned>, - Renderer: renderer::Text + 'a, + Renderer: text::Renderer + 'a, Message: 'static, { fn into(self) -> Element<'a, Message, Renderer> { diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 91de8be5..afe85b76 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -6,9 +6,9 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; +use crate::text; use crate::touch; -use crate::widget::text; -use crate::widget::{Row, Text}; +use crate::widget::{self, Row, Text}; use crate::{ Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Widget, @@ -43,7 +43,7 @@ pub use iced_style::radio::{Style, StyleSheet}; /// /// ![Radio buttons drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/radio.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Radio<'a, Message, Renderer: renderer::Text> { +pub struct Radio<'a, Message, Renderer: text::Renderer> { is_selected: bool, on_click: Message, label: String, @@ -56,7 +56,7 @@ pub struct Radio<'a, Message, Renderer: renderer::Text> { style_sheet: &'a dyn StyleSheet, } -impl<'a, Message, Renderer: renderer::Text> Radio<'a, Message, Renderer> +impl<'a, Message, Renderer: text::Renderer> Radio<'a, Message, Renderer> where Message: Clone, { @@ -145,7 +145,7 @@ impl<'a, Message, Renderer> Widget for Radio<'a, Message, Renderer> where Message: Clone, - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.width @@ -267,7 +267,7 @@ where { let label_layout = children.next().unwrap(); - text::draw( + widget::text::draw( renderer, style, label_layout, @@ -293,7 +293,7 @@ impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + renderer::Text, + Renderer: 'a + text::Renderer, { fn from( radio: Radio<'a, Message, Renderer>, diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 563ab8c4..79688b28 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -2,12 +2,11 @@ use crate::alignment; use crate::layout; use crate::renderer; +use crate::text; use crate::{ Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, }; -pub use iced_core::text::Hit; - use std::hash::Hash; /// A paragraph of text. @@ -24,7 +23,7 @@ use std::hash::Hash; /// /// ![Text drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text.png?raw=true) #[derive(Debug)] -pub struct Text { +pub struct Text { content: String, size: Option, color: Option, @@ -35,7 +34,7 @@ pub struct Text { vertical_alignment: alignment::Vertical, } -impl Text { +impl Text { /// Create a new fragment of [`Text`] with the given contents. pub fn new>(label: T) -> Self { Text { @@ -103,7 +102,7 @@ impl Text { impl Widget for Text where - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.width @@ -175,7 +174,7 @@ pub fn draw( horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, ) where - Renderer: renderer::Text, + Renderer: text::Renderer, { let bounds = layout.bounds(); @@ -191,7 +190,7 @@ pub fn draw( alignment::Vertical::Bottom => bounds.y + bounds.height, }; - renderer.fill_text(renderer::text::Section { + renderer.fill_text(crate::text::Text { content, size: f32::from(size.unwrap_or(renderer.default_size())), bounds: Rectangle { x, y, ..bounds }, @@ -205,14 +204,14 @@ pub fn draw( impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: renderer::Text + 'a, + Renderer: text::Renderer + 'a, { fn from(text: Text) -> Element<'a, Message, Renderer> { Element::new(text) } } -impl Clone for Text { +impl Clone for Text { fn clone(&self) -> Self { Self { content: self.content.clone(), diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 5d67ddfe..a3641330 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -17,6 +17,7 @@ use crate::keyboard; use crate::layout; use crate::mouse::{self, click}; use crate::renderer; +use crate::text::{self, Text}; use crate::touch; use crate::{ Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, @@ -53,7 +54,7 @@ pub use iced_style::text_input::{Style, StyleSheet}; /// ``` /// ![Text input drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text_input.png?raw=true) #[allow(missing_debug_implementations)] -pub struct TextInput<'a, Message, Renderer: renderer::Text> { +pub struct TextInput<'a, Message, Renderer: text::Renderer> { state: &'a mut State, placeholder: String, value: Value, @@ -71,7 +72,7 @@ pub struct TextInput<'a, Message, Renderer: renderer::Text> { impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> where Message: Clone, - Renderer: renderer::Text, + Renderer: text::Renderer, { /// Creates a new [`TextInput`]. /// @@ -166,7 +167,7 @@ impl<'a, Message, Renderer> Widget for TextInput<'a, Message, Renderer> where Message: Clone, - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.width @@ -728,7 +729,7 @@ where renderer.fill_rectangle(cursor); } - renderer.fill_text(renderer::text::Section { + renderer.fill_text(Text { content: if text.is_empty() { &self.placeholder } else { @@ -776,7 +777,7 @@ impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, - Renderer: 'a + renderer::Text, + Renderer: 'a + text::Renderer, { fn from( text_input: TextInput<'a, Message, Renderer>, @@ -877,7 +878,7 @@ fn offset( state: &State, ) -> f32 where - Renderer: renderer::Text, + Renderer: text::Renderer, { if state.is_focused() { let cursor = state.cursor(); @@ -911,7 +912,7 @@ fn measure_cursor_and_scroll_offset( font: Renderer::Font, ) -> (f32, f32) where - Renderer: renderer::Text, + Renderer: text::Renderer, { let text_before_cursor = value.until(cursor_index).to_string(); @@ -935,7 +936,7 @@ fn find_cursor_position( x: f32, ) -> Option where - Renderer: renderer::Text, + Renderer: text::Renderer, { let size = size.unwrap_or(renderer.default_size()); @@ -950,5 +951,5 @@ where Point::new(x + offset, text_bounds.height / 2.0), true, ) - .map(renderer::text::Hit::cursor) + .map(text::Hit::cursor) } diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 20cfea74..e5229d52 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -6,7 +6,7 @@ use crate::event; use crate::layout; use crate::mouse; use crate::renderer; -use crate::widget::text; +use crate::text; use crate::widget::{Row, Text}; use crate::{ Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, @@ -31,7 +31,7 @@ pub use iced_style::toggler::{Style, StyleSheet}; /// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b)); /// ``` #[allow(missing_debug_implementations)] -pub struct Toggler { +pub struct Toggler { is_active: bool, on_toggle: Box Message>, label: Option, @@ -44,7 +44,7 @@ pub struct Toggler { style_sheet: Box, } -impl Toggler { +impl Toggler { /// The default size of a [`Toggler`]. pub const DEFAULT_SIZE: u16 = 20; @@ -126,7 +126,7 @@ impl Toggler { impl Widget for Toggler where - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.width @@ -223,7 +223,7 @@ where if let Some(label) = &self.label { let label_layout = children.next().unwrap(); - text::draw( + crate::widget::text::draw( renderer, style, label_layout, @@ -297,7 +297,7 @@ where impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + renderer::Text, + Renderer: 'a + text::Renderer, Message: 'a, { fn from( diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index a00158f6..a7f3a042 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -6,6 +6,7 @@ use iced_core::Rectangle; use crate::event; use crate::layout; use crate::renderer; +use crate::text; use crate::widget::container; use crate::widget::text::Text; use crate::{ @@ -15,7 +16,7 @@ use crate::{ /// An element to display a widget over another. #[allow(missing_debug_implementations)] -pub struct Tooltip<'a, Message, Renderer: renderer::Text> { +pub struct Tooltip<'a, Message, Renderer: text::Renderer> { content: Element<'a, Message, Renderer>, tooltip: Text, position: Position, @@ -26,7 +27,7 @@ pub struct Tooltip<'a, Message, Renderer: renderer::Text> { impl<'a, Message, Renderer> Tooltip<'a, Message, Renderer> where - Renderer: renderer::Text, + Renderer: text::Renderer, { /// The default padding of a [`Tooltip`] drawn by this renderer. const DEFAULT_PADDING: u16 = 5; @@ -100,7 +101,7 @@ pub enum Position { impl<'a, Message, Renderer> Widget for Tooltip<'a, Message, Renderer> where - Renderer: renderer::Text, + Renderer: text::Renderer, { fn width(&self) -> Length { self.content.width() @@ -260,7 +261,7 @@ where impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + renderer::Text, + Renderer: 'a + text::Renderer, Message: 'a, { fn from( -- cgit From c4186a71b746b603984e5fe1926a8cef6e8dcfcb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 16:20:50 +0700 Subject: Introduce first-class `image` module in `iced_native` --- native/src/widget/image.rs | 131 ++------------------------------------ native/src/widget/image/viewer.rs | 2 +- 2 files changed, 5 insertions(+), 128 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index d23d393a..66e95265 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -2,15 +2,12 @@ pub mod viewer; pub use viewer::Viewer; +use crate::image::{self, Handle}; use crate::layout; use crate::renderer; use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; -use std::{ - hash::{Hash, Hasher as _}, - path::PathBuf, - sync::Arc, -}; +use std::hash::Hash; /// A frame that displays an image while keeping aspect ratio. /// @@ -55,7 +52,7 @@ impl Image { impl Widget for Image where - Renderer: self::Renderer, + Renderer: image::Renderer, { fn width(&self) -> Length { self.width @@ -111,129 +108,9 @@ where } } -/// An [`Image`] handle. -#[derive(Debug, Clone)] -pub struct Handle { - id: u64, - data: Arc, -} - -impl Handle { - /// Creates an image [`Handle`] pointing to the image of the given path. - /// - /// Makes an educated guess about the image format by examining the data in the file. - pub fn from_path>(path: T) -> Handle { - Self::from_data(Data::Path(path.into())) - } - - /// Creates an image [`Handle`] containing the image pixels directly. This - /// function expects the input data to be provided as a `Vec` of BGRA - /// pixels. - /// - /// This is useful if you have already decoded your image. - pub fn from_pixels(width: u32, height: u32, pixels: Vec) -> Handle { - Self::from_data(Data::Pixels { - width, - height, - pixels, - }) - } - - /// Creates an image [`Handle`] containing the image data directly. - /// - /// Makes an educated guess about the image format by examining the given data. - /// - /// This is useful if you already have your image loaded in-memory, maybe - /// because you downloaded or generated it procedurally. - pub fn from_memory(bytes: Vec) -> Handle { - Self::from_data(Data::Bytes(bytes)) - } - - fn from_data(data: Data) -> Handle { - let mut hasher = Hasher::default(); - data.hash(&mut hasher); - - Handle { - id: hasher.finish(), - data: Arc::new(data), - } - } - - /// Returns the unique identifier of the [`Handle`]. - pub fn id(&self) -> u64 { - self.id - } - - /// Returns a reference to the image [`Data`]. - pub fn data(&self) -> &Data { - &self.data - } -} - -impl From for Handle -where - T: Into, -{ - fn from(path: T) -> Handle { - Handle::from_path(path.into()) - } -} - -impl Hash for Handle { - fn hash(&self, state: &mut H) { - self.id.hash(state); - } -} - -/// The data of an [`Image`]. -#[derive(Clone, Hash)] -pub enum Data { - /// File data - Path(PathBuf), - - /// In-memory data - Bytes(Vec), - - /// Decoded image pixels in BGRA format. - Pixels { - /// The width of the image. - width: u32, - /// The height of the image. - height: u32, - /// The pixels. - pixels: Vec, - }, -} - -impl std::fmt::Debug for Data { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Data::Path(path) => write!(f, "Path({:?})", path), - Data::Bytes(_) => write!(f, "Bytes(...)"), - Data::Pixels { width, height, .. } => { - write!(f, "Pixels({} * {})", width, height) - } - } - } -} - -/// The renderer of an [`Image`]. -/// -/// Your [renderer] will need to implement this trait before being able to use -/// an [`Image`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// Returns the dimensions of an [`Image`] located on the given path. - fn dimensions(&self, handle: &Handle) -> (u32, u32); - - // Draws an [`Image`]. - fn draw(&mut self, handle: Handle, bounds: Rectangle); -} - impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: image::Renderer, { fn from(image: Image) -> Element<'a, Message, Renderer> { Element::new(image) diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index d3c794a7..d9eccfad 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -1,9 +1,9 @@ //! Zoom and pan on an image. use crate::event::{self, Event}; +use crate::image; use crate::layout; use crate::mouse; use crate::renderer; -use crate::widget::image; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, -- cgit From 9a3c81f336b8e29c64471026860f3c9d8b56348c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 16:24:31 +0700 Subject: Introduce first-class `svg` module in `iced_native` --- native/src/widget/svg.rs | 93 +++--------------------------------------------- 1 file changed, 4 insertions(+), 89 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 785b8054..f212dfcb 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -1,11 +1,11 @@ //! Display vector graphics in your application. use crate::layout; use crate::renderer; +use crate::svg::{self, Handle}; use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; -use std::hash::{Hash, Hasher as _}; +use std::hash::Hash; use std::path::PathBuf; -use std::sync::Arc; /// A vector graphics image. /// @@ -51,7 +51,7 @@ impl Svg { impl Widget for Svg where - Renderer: self::Renderer, + Renderer: svg::Renderer, { fn width(&self) -> Length { self.width @@ -106,94 +106,9 @@ where } } -/// An [`Svg`] handle. -#[derive(Debug, Clone)] -pub struct Handle { - id: u64, - data: Arc, -} - -impl Handle { - /// Creates an SVG [`Handle`] pointing to the vector image of the given - /// path. - pub fn from_path(path: impl Into) -> Handle { - Self::from_data(Data::Path(path.into())) - } - - /// Creates an SVG [`Handle`] from raw bytes containing either an SVG string - /// or gzip compressed data. - /// - /// This is useful if you already have your SVG data in-memory, maybe - /// because you downloaded or generated it procedurally. - pub fn from_memory(bytes: impl Into>) -> Handle { - Self::from_data(Data::Bytes(bytes.into())) - } - - fn from_data(data: Data) -> Handle { - let mut hasher = Hasher::default(); - data.hash(&mut hasher); - - Handle { - id: hasher.finish(), - data: Arc::new(data), - } - } - - /// Returns the unique identifier of the [`Handle`]. - pub fn id(&self) -> u64 { - self.id - } - - /// Returns a reference to the SVG [`Data`]. - pub fn data(&self) -> &Data { - &self.data - } -} - -impl Hash for Handle { - fn hash(&self, state: &mut H) { - self.id.hash(state); - } -} - -/// The data of an [`Svg`]. -#[derive(Clone, Hash)] -pub enum Data { - /// File data - Path(PathBuf), - - /// In-memory data - /// - /// Can contain an SVG string or a gzip compressed data. - Bytes(Vec), -} - -impl std::fmt::Debug for Data { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Data::Path(path) => write!(f, "Path({:?})", path), - Data::Bytes(_) => write!(f, "Bytes(...)"), - } - } -} - -/// The renderer of an [`Svg`]. -/// -/// Your [renderer] will need to implement this trait before being able to use -/// an [`Svg`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// Returns the default dimensions of an [`Svg`] for the given [`Handle`]. - fn dimensions(&self, handle: &Handle) -> (u32, u32); - - // Draws an [`Svg`]. - fn draw(&mut self, handle: Handle, bounds: Rectangle); -} - impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: svg::Renderer, { fn from(icon: Svg) -> Element<'a, Message, Renderer> { Element::new(icon) -- cgit From d36ce33a95c277ee8fe45555df17daf21ef02ef8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 16:53:18 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Button` --- native/src/widget/button.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index a577fe84..588833a4 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -66,7 +66,7 @@ pub struct Button<'a, Message, Renderer> { min_width: u32, min_height: u32, padding: Padding, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer> Button<'a, Message, Renderer> @@ -131,8 +131,11 @@ where } /// Sets the style of the [`Button`]. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -- cgit From fcc282bd76c88f389d510411b0ae73e1a4eaf317 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 16:58:02 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Checkbox` --- native/src/widget/checkbox.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 624e01d6..b19a0a25 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -44,7 +44,7 @@ pub struct Checkbox<'a, Message, Renderer: text::Renderer> { text_size: Option, font: Renderer::Font, text_color: Option, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> { @@ -119,8 +119,11 @@ impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> { } /// Sets the style of the [`Checkbox`]. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -- cgit From 40a5de581144886571504b762719f057dbb2e871 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:02:59 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Container` --- native/src/widget/container.rs | 9 ++++++--- native/src/widget/pane_grid/content.rs | 9 ++++++--- native/src/widget/pane_grid/title_bar.rs | 9 ++++++--- native/src/widget/tooltip.rs | 9 ++++++--- 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 006e07c6..5ad07d6d 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -28,7 +28,7 @@ pub struct Container<'a, Message, Renderer> { max_height: u32, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, content: Element<'a, Message, Renderer>, } @@ -109,8 +109,11 @@ where } /// Sets the style of the [`Container`]. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index 83d96917..d8da6d33 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -14,7 +14,7 @@ use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; pub struct Content<'a, Message, Renderer> { title_bar: Option>, body: Element<'a, Message, Renderer>, - style_sheet: &'a dyn container::StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer> Content<'a, Message, Renderer> @@ -40,8 +40,11 @@ where } /// Sets the style of the [`Content`]. - pub fn style(mut self, style_sheet: &'a dyn container::StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 2d66ba6c..ffd59488 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -17,7 +17,7 @@ pub struct TitleBar<'a, Message, Renderer> { controls: Option>, padding: Padding, always_show_controls: bool, - style_sheet: &'a dyn container::StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer> @@ -54,8 +54,11 @@ where } /// Sets the style of the [`TitleBar`]. - pub fn style(mut self, style: &'a dyn container::StyleSheet) -> Self { - self.style_sheet = style; + pub fn style( + mut self, + style: impl Into>, + ) -> Self { + self.style_sheet = style.into(); self } diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index a7f3a042..5a6cd923 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -20,7 +20,7 @@ pub struct Tooltip<'a, Message, Renderer: text::Renderer> { content: Element<'a, Message, Renderer>, tooltip: Text, position: Position, - style_sheet: &'a dyn container::StyleSheet, + style_sheet: Box, gap: u16, padding: u16, } @@ -77,8 +77,11 @@ where } /// Sets the style of the [`Tooltip`]. - pub fn style(mut self, style_sheet: &'a dyn container::StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -- cgit From 89d50c0243fcb70442c78bbff207d0328b33e158 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:04:44 +0700 Subject: Reintroduce `Box` for `style_sheet` in `PaneGrid` --- native/src/widget/pane_grid.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 22c18c05..48243c0b 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -99,7 +99,7 @@ pub struct PaneGrid<'a, Message, Renderer> { on_click: Option Message + 'a>>, on_drag: Option Message + 'a>>, on_resize: Option<(u16, Box Message + 'a>)>, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer> @@ -191,8 +191,8 @@ where } /// Sets the style of the [`PaneGrid`]. - pub fn style(mut self, style: &'a dyn StyleSheet) -> Self { - self.style_sheet = style; + pub fn style(mut self, style: impl Into>) -> Self { + self.style_sheet = style.into(); self } } -- cgit From 6504dca05995b376479c3d0bd9e47f5f6b601788 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:06:05 +0700 Subject: Introduce state lifetime for `style_sheet` in `PickList` --- native/src/widget/pick_list.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 3a393e14..9d2f63db 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -36,7 +36,7 @@ where padding: Padding, text_size: Option, font: Renderer::Font, - style_sheet: Box, + style_sheet: Box, } /// The local state of a [`PickList`]. @@ -138,7 +138,7 @@ where /// Sets the style of the [`PickList`]. pub fn style( mut self, - style_sheet: impl Into>, + style_sheet: impl Into>, ) -> Self { self.style_sheet = style_sheet.into(); self -- cgit From d758006ee91aa0fdb70eaa67abbfad36be02c7be Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:08:19 +0700 Subject: Introduce state lifetime for `style_sheet` in `ProgressBar` --- native/src/widget/progress_bar.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 48bf485e..1f83de10 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -21,15 +21,15 @@ pub use iced_style::progress_bar::{Style, StyleSheet}; /// /// ![Progress bar drawn with `iced_wgpu`](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png) #[allow(missing_debug_implementations)] -pub struct ProgressBar { +pub struct ProgressBar<'a> { range: RangeInclusive, value: f32, width: Length, height: Option, - style_sheet: Box, + style_sheet: Box, } -impl ProgressBar { +impl<'a> ProgressBar<'a> { /// The default height of a [`ProgressBar`]. pub const DEFAULT_HEIGHT: u16 = 30; @@ -63,14 +63,14 @@ impl ProgressBar { /// Sets the style of the [`ProgressBar`]. pub fn style( mut self, - style_sheet: impl Into>, + style_sheet: impl Into>, ) -> Self { self.style_sheet = style_sheet.into(); self } } -impl Widget for ProgressBar +impl<'a, Message, Renderer> Widget for ProgressBar<'a> where Renderer: crate::Renderer, { @@ -147,12 +147,13 @@ where } } -impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> +impl<'a, Message, Renderer> From> + for Element<'a, Message, Renderer> where Renderer: 'a + crate::Renderer, Message: 'a, { - fn from(progress_bar: ProgressBar) -> Element<'a, Message, Renderer> { + fn from(progress_bar: ProgressBar<'a>) -> Element<'a, Message, Renderer> { Element::new(progress_bar) } } -- cgit From bd7b086ec1f9d428945f05fb12bda157f9e77dfd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:14:10 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Radio` --- native/src/widget/radio.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index afe85b76..eb732dc3 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -53,7 +53,7 @@ pub struct Radio<'a, Message, Renderer: text::Renderer> { text_size: Option, text_color: Option, font: Renderer::Font, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer: text::Renderer> Radio<'a, Message, Renderer> @@ -135,8 +135,11 @@ where } /// Sets the style of the [`Radio`] button. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } } -- cgit From 48490c3d878da1e2760c7701e80586c3653d5bd8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:34:58 +0700 Subject: Introduce state lifetime for `style_sheet` in `Rule` --- native/src/widget/rule.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index f0d50006..8f4e66a6 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -12,14 +12,14 @@ pub use iced_style::rule::{FillMode, Style, StyleSheet}; /// Display a horizontal or vertical rule for dividing content. #[allow(missing_debug_implementations)] -pub struct Rule { +pub struct Rule<'a> { width: Length, height: Length, is_horizontal: bool, - style_sheet: Box, + style_sheet: Box, } -impl Rule { +impl<'a> Rule<'a> { /// Creates a horizontal [`Rule`] for dividing content by the given vertical spacing. pub fn horizontal(spacing: u16) -> Self { Rule { @@ -43,14 +43,14 @@ impl Rule { /// Sets the style of the [`Rule`]. pub fn style( mut self, - style_sheet: impl Into>, + style_sheet: impl Into>, ) -> Self { self.style_sheet = style_sheet.into(); self } } -impl Widget for Rule +impl<'a, Message, Renderer> Widget for Rule<'a> where Renderer: crate::Renderer, { @@ -131,12 +131,12 @@ where } } -impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> +impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Renderer: 'a + crate::Renderer, Message: 'a, { - fn from(rule: Rule) -> Element<'a, Message, Renderer> { + fn from(rule: Rule<'a>) -> Element<'a, Message, Renderer> { Element::new(rule) } } -- cgit From eed19dcf81334d0849744f1918ba880d5a7acc1c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:39:24 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Scrollable` --- native/src/widget/scrollable.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 781fe73e..05e9b347 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -27,7 +27,7 @@ pub struct Scrollable<'a, Message, Renderer> { scroller_width: u16, content: Column<'a, Message, Renderer>, on_scroll: Option Message>>, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> { @@ -123,8 +123,11 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> { } /// Sets the style of the [`Scrollable`] . - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } -- cgit From 0c76e0307ff7d4450c354812f8a25047f24948b4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:42:43 +0700 Subject: Reintroduce `Box` for `style_sheet` in `Slider` --- native/src/widget/slider.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 977a5240..ee9db6cf 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -50,7 +50,7 @@ pub struct Slider<'a, T, Message> { on_release: Option, width: Length, height: u16, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, T, Message> Slider<'a, T, Message> @@ -127,8 +127,11 @@ where } /// Sets the style of the [`Slider`]. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { - self.style_sheet = style_sheet; + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { + self.style_sheet = style_sheet.into(); self } -- cgit From 0d3c9ef7bd3d0a0abecdf8e8b5391e32773ca20e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:45:57 +0700 Subject: Reintroduce `Box` for `style_sheet` in `TextInput` --- native/src/widget/text_input.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index a3641330..5be1d3d6 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -66,7 +66,7 @@ pub struct TextInput<'a, Message, Renderer: text::Renderer> { size: Option, on_change: Box Message>, on_submit: Option, - style_sheet: &'a dyn StyleSheet, + style_sheet: Box, } impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> @@ -152,7 +152,10 @@ where } /// Sets the style of the [`TextInput`]. - pub fn style(mut self, style_sheet: &'a dyn StyleSheet) -> Self { + pub fn style( + mut self, + style_sheet: impl Into>, + ) -> Self { self.style_sheet = style_sheet.into(); self } -- cgit From c9ed15782c3a62fcbfe56a141837b384ada82aaa Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 31 Oct 2021 17:48:23 +0700 Subject: Introduce state lifetime for `style_sheet` in `Toggler` --- native/src/widget/toggler.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index e5229d52..961d2936 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -31,7 +31,7 @@ pub use iced_style::toggler::{Style, StyleSheet}; /// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b)); /// ``` #[allow(missing_debug_implementations)] -pub struct Toggler { +pub struct Toggler<'a, Message, Renderer: text::Renderer> { is_active: bool, on_toggle: Box Message>, label: Option, @@ -41,10 +41,10 @@ pub struct Toggler { text_alignment: alignment::Horizontal, spacing: u16, font: Renderer::Font, - style_sheet: Box, + style_sheet: Box, } -impl Toggler { +impl<'a, Message, Renderer: text::Renderer> Toggler<'a, Message, Renderer> { /// The default size of a [`Toggler`]. pub const DEFAULT_SIZE: u16 = 20; @@ -117,14 +117,15 @@ impl Toggler { /// Sets the style of the [`Toggler`]. pub fn style( mut self, - style_sheet: impl Into>, + style_sheet: impl Into>, ) -> Self { self.style_sheet = style_sheet.into(); self } } -impl Widget for Toggler +impl<'a, Message, Renderer> Widget + for Toggler<'a, Message, Renderer> where Renderer: text::Renderer, { @@ -294,14 +295,14 @@ where } } -impl<'a, Message, Renderer> From> +impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Renderer: 'a + text::Renderer, Message: 'a, { fn from( - toggler: Toggler, + toggler: Toggler<'a, Message, Renderer>, ) -> Element<'a, Message, Renderer> { Element::new(toggler) } -- cgit From e50bb1dd2c65677f6fce77ca9d7d5e001729c162 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 1 Nov 2021 14:58:50 +0700 Subject: Fix missing lifetime in doc example for `Toggler` --- native/src/widget/toggler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 961d2936..fb7d2642 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -20,7 +20,7 @@ pub use iced_style::toggler::{Style, StyleSheet}; /// # Example /// /// ``` -/// # type Toggler = iced_native::widget::Toggler; +/// # type Toggler<'a, Message> = iced_native::widget::Toggler<'a, Message, iced_native::renderer::Null>; /// # /// pub enum Message { /// TogglerToggled(bool), -- cgit From a1db8d62c00dc355e677b98fb620cba3b478ae53 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 1 Nov 2021 16:29:28 +0700 Subject: Reintroduce `draw` method in `TextInput` ... which allows overriding the rendered value. --- native/src/widget/text_input.rs | 330 +++++++++++++++++++++------------------- 1 file changed, 174 insertions(+), 156 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 2d5f6815..5dd68f81 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -166,6 +166,179 @@ where } } +impl<'a, Message, Renderer> TextInput<'a, Message, Renderer> +where + Renderer: text::Renderer, +{ + /// Draws the [`TextInput`] with the given [`Renderer`], overriding its + /// [`Value`] if provided. + pub fn draw( + &self, + renderer: &mut Renderer, + layout: Layout<'_>, + cursor_position: Point, + value: Option<&Value>, + ) { + let value = value.unwrap_or(&self.value); + let secure_value = self.is_secure.then(|| value.secure()); + let value = secure_value.as_ref().unwrap_or(&value); + + let bounds = layout.bounds(); + let text_bounds = layout.children().next().unwrap().bounds(); + + let is_mouse_over = bounds.contains(cursor_position); + + let style = if self.state.is_focused() { + self.style_sheet.focused() + } else if is_mouse_over { + self.style_sheet.hovered() + } else { + self.style_sheet.active() + }; + + renderer.fill_rectangle(renderer::Quad { + bounds, + background: style.background, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }); + + let text = value.to_string(); + let size = self.size.unwrap_or(renderer.default_size()); + + let (cursor, offset) = if self.state.is_focused() { + match self.state.cursor.state(&value) { + cursor::State::Index(position) => { + let (text_value_width, offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + position, + self.font, + ); + + ( + Some(renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + text_value_width, + y: text_bounds.y, + width: 1.0, + height: text_bounds.height, + }, + background: Background::Color( + self.style_sheet.value_color(), + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }), + offset, + ) + } + cursor::State::Selection { start, end } => { + let left = start.min(end); + let right = end.max(start); + + let (left_position, left_offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + left, + self.font, + ); + + let (right_position, right_offset) = + measure_cursor_and_scroll_offset( + renderer, + text_bounds, + &value, + size, + right, + self.font, + ); + + let width = right_position - left_position; + + ( + Some(renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + left_position, + y: text_bounds.y, + width, + height: text_bounds.height, + }, + background: Background::Color( + self.style_sheet.selection_color(), + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }), + if end == right { + right_offset + } else { + left_offset + }, + ) + } + } + } else { + (None, 0.0) + }; + + let text_width = renderer.measure_width( + if text.is_empty() { + &self.placeholder + } else { + &text + }, + size, + self.font, + ); + + let render = |renderer: &mut Renderer| { + if let Some(cursor) = cursor { + renderer.fill_rectangle(cursor); + } + + renderer.fill_text(Text { + content: if text.is_empty() { + &self.placeholder + } else { + &text + }, + color: if text.is_empty() { + self.style_sheet.placeholder_color() + } else { + self.style_sheet.value_color() + }, + font: self.font, + bounds: Rectangle { + y: text_bounds.center_y(), + width: f32::INFINITY, + ..text_bounds + }, + size: f32::from(size), + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Center, + }); + }; + + if text_width > text_bounds.width { + renderer.with_layer(text_bounds, |renderer| { + renderer.with_translation(Vector::new(-offset, 0.0), render) + }); + } else { + render(renderer); + } + } +} + impl<'a, Message, Renderer> Widget for TextInput<'a, Message, Renderer> where @@ -604,162 +777,7 @@ where cursor_position: Point, _viewport: &Rectangle, ) { - let secure_value = self.is_secure.then(|| self.value.secure()); - let value = secure_value.as_ref().unwrap_or(&self.value); - - let bounds = layout.bounds(); - let text_bounds = layout.children().next().unwrap().bounds(); - - let is_mouse_over = bounds.contains(cursor_position); - - let style = if self.state.is_focused() { - self.style_sheet.focused() - } else if is_mouse_over { - self.style_sheet.hovered() - } else { - self.style_sheet.active() - }; - - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style.background, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); - - let text = value.to_string(); - let size = self.size.unwrap_or(renderer.default_size()); - - let (cursor, offset) = if self.state.is_focused() { - match self.state.cursor.state(&value) { - cursor::State::Index(position) => { - let (text_value_width, offset) = - measure_cursor_and_scroll_offset( - renderer, - text_bounds, - &value, - size, - position, - self.font, - ); - - ( - Some(renderer::Quad { - bounds: Rectangle { - x: text_bounds.x + text_value_width, - y: text_bounds.y, - width: 1.0, - height: text_bounds.height, - }, - background: Background::Color( - self.style_sheet.value_color(), - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }), - offset, - ) - } - cursor::State::Selection { start, end } => { - let left = start.min(end); - let right = end.max(start); - - let (left_position, left_offset) = - measure_cursor_and_scroll_offset( - renderer, - text_bounds, - &value, - size, - left, - self.font, - ); - - let (right_position, right_offset) = - measure_cursor_and_scroll_offset( - renderer, - text_bounds, - &value, - size, - right, - self.font, - ); - - let width = right_position - left_position; - - ( - Some(renderer::Quad { - bounds: Rectangle { - x: text_bounds.x + left_position, - y: text_bounds.y, - width, - height: text_bounds.height, - }, - background: Background::Color( - self.style_sheet.selection_color(), - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }), - if end == right { - right_offset - } else { - left_offset - }, - ) - } - } - } else { - (None, 0.0) - }; - - let text_width = renderer.measure_width( - if text.is_empty() { - &self.placeholder - } else { - &text - }, - size, - self.font, - ); - - let render = |renderer: &mut Renderer| { - if let Some(cursor) = cursor { - renderer.fill_rectangle(cursor); - } - - renderer.fill_text(Text { - content: if text.is_empty() { - &self.placeholder - } else { - &text - }, - color: if text.is_empty() { - self.style_sheet.placeholder_color() - } else { - self.style_sheet.value_color() - }, - font: self.font, - bounds: Rectangle { - y: text_bounds.center_y(), - width: f32::INFINITY, - ..text_bounds - }, - size: f32::from(size), - horizontal_alignment: alignment::Horizontal::Left, - vertical_alignment: alignment::Vertical::Center, - }); - }; - - if text_width > text_bounds.width { - renderer.with_layer(text_bounds, |renderer| { - renderer.with_translation(Vector::new(-offset, 0.0), render) - }); - } else { - render(renderer); - } + self.draw(renderer, layout, cursor_position, None) } fn hash_layout(&self, state: &mut Hasher) { -- cgit From c330bb1b69d55d767fa5bb2e0fcc059fbbe07d07 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 1 Nov 2021 17:39:46 +0700 Subject: Fix `mouse_interaction` using wrong layout in `PaneGrid` ... when no titlebar is present. --- native/src/widget/pane_grid/content.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index d8da6d33..efb3493b 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -204,10 +204,9 @@ where viewport: &Rectangle, cursor_position: Point, ) -> mouse::Interaction { - let mut children = layout.children(); - let (body_layout, title_bar_interaction) = if let Some(title_bar) = &self.title_bar { + let mut children = layout.children(); let title_bar_layout = children.next().unwrap(); let is_over_pick_area = title_bar @@ -225,7 +224,7 @@ where (children.next().unwrap(), mouse_interaction) } else { - (children.next().unwrap(), mouse::Interaction::default()) + (layout, mouse::Interaction::default()) }; self.body -- cgit From 631e95ee0be01dc7f5e5183e1429972aee37787f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 2 Nov 2021 15:03:29 +0700 Subject: Move `viewport` argument to last position in `mouse_interaction` methods This keeps the order of the arguments consistent with `draw`. --- native/src/widget/button.rs | 2 +- native/src/widget/checkbox.rs | 2 +- native/src/widget/column.rs | 4 ++-- native/src/widget/container.rs | 4 ++-- native/src/widget/image/viewer.rs | 2 +- native/src/widget/pane_grid.rs | 4 ++-- native/src/widget/pane_grid/content.rs | 6 +++--- native/src/widget/pane_grid/title_bar.rs | 6 +++--- native/src/widget/pick_list.rs | 2 +- native/src/widget/radio.rs | 2 +- native/src/widget/row.rs | 4 ++-- native/src/widget/scrollable.rs | 4 ++-- native/src/widget/slider.rs | 2 +- native/src/widget/text_input.rs | 2 +- native/src/widget/toggler.rs | 2 +- native/src/widget/tooltip.rs | 11 +++++++++++ 16 files changed, 35 insertions(+), 24 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 588833a4..0d9eeebd 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -251,8 +251,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { let is_mouse_over = layout.bounds().contains(cursor_position); let is_disabled = self.on_press.is_none(); diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index b19a0a25..04f62cd9 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -193,8 +193,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { if layout.bounds().contains(cursor_position) { mouse::Interaction::Pointer diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 1d2c8485..0d4d6fa7 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -167,8 +167,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { self.children .iter() @@ -176,8 +176,8 @@ where .map(|(child, layout)| { child.widget.mouse_interaction( layout, - viewport, cursor_position, + viewport, ) }) .max() diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 5ad07d6d..9e3d0193 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -182,13 +182,13 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { self.content.widget.mouse_interaction( layout.children().next().unwrap(), - viewport, cursor_position, + viewport, ) } diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index d9eccfad..95e5c6e4 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -284,8 +284,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { let bounds = layout.bounds(); let is_mouse_over = bounds.contains(cursor_position); diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 48243c0b..d98369e4 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -474,8 +474,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { if self.state.picked_pane().is_some() { return mouse::Interaction::Grab; @@ -492,7 +492,7 @@ where .iter() .zip(layout.children()) .map(|((_pane, content), layout)| { - content.mouse_interaction(layout, viewport, cursor_position) + content.mouse_interaction(layout, cursor_position, viewport) }) .max() .unwrap_or_default() diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index efb3493b..c44506dd 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -201,8 +201,8 @@ where pub(crate) fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { let (body_layout, title_bar_interaction) = if let Some(title_bar) = &self.title_bar { @@ -218,8 +218,8 @@ where let mouse_interaction = title_bar.mouse_interaction( title_bar_layout, - viewport, cursor_position, + viewport, ); (children.next().unwrap(), mouse_interaction) @@ -228,7 +228,7 @@ where }; self.body - .mouse_interaction(body_layout, viewport, cursor_position) + .mouse_interaction(body_layout, cursor_position, viewport) .max(title_bar_interaction) } diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index ffd59488..070cf404 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -256,8 +256,8 @@ where pub(crate) fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { let mut children = layout.children(); let padded = children.next().unwrap(); @@ -267,15 +267,15 @@ where let title_interaction = self.content.mouse_interaction( title_layout, - viewport, cursor_position, + viewport, ); if let Some(controls) = &self.controls { let controls_layout = children.next().unwrap(); controls - .mouse_interaction(controls_layout, viewport, cursor_position) + .mouse_interaction(controls_layout, cursor_position, viewport) .max(title_interaction) } else { title_interaction diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 9d2f63db..a7fef37b 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -329,8 +329,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { let bounds = layout.bounds(); let is_mouse_over = bounds.contains(cursor_position); diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index eb732dc3..7d39c526 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -207,8 +207,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { if layout.bounds().contains(cursor_position) { mouse::Interaction::Pointer diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index af83f106..6fe3284b 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -166,8 +166,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - viewport: &Rectangle, cursor_position: Point, + viewport: &Rectangle, ) -> mouse::Interaction { self.children .iter() @@ -175,8 +175,8 @@ where .map(|(child, layout)| { child.widget.mouse_interaction( layout, - viewport, cursor_position, + viewport, ) }) .max() diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 05e9b347..00f80bc6 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -426,8 +426,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); @@ -453,11 +453,11 @@ where self.content.mouse_interaction( content_layout, + cursor_position, &Rectangle { y: bounds.y + offset as f32, ..bounds }, - cursor_position, ) } } diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index ee9db6cf..01053081 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -342,8 +342,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { let bounds = layout.bounds(); let is_mouse_over = bounds.contains(cursor_position); diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 5dd68f81..db60b553 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -759,8 +759,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { if layout.bounds().contains(cursor_position) { mouse::Interaction::Text diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index fb7d2642..78e3d5ef 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -194,8 +194,8 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - _viewport: &Rectangle, cursor_position: Point, + _viewport: &Rectangle, ) -> mouse::Interaction { if layout.bounds().contains(cursor_position) { mouse::Interaction::Pointer diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 5a6cd923..c35005e0 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -5,6 +5,7 @@ use iced_core::Rectangle; use crate::event; use crate::layout; +use crate::mouse; use crate::renderer; use crate::text; use crate::widget::container; @@ -141,6 +142,16 @@ where ) } + fn mouse_interaction( + &self, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + ) -> mouse::Interaction { + self.content + .mouse_interaction(layout, cursor_position, viewport) + } + fn draw( &self, renderer: &mut Renderer, -- cgit From 023aded2772f0cd6abd716fe5c8624d5d22e21fa Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 4 Nov 2021 19:22:29 +0700 Subject: Rename `fill_rectangle` to `fill_quad` in `Renderer` --- native/src/widget/button.rs | 38 +++++++++++--------- native/src/widget/checkbox.rs | 16 +++++---- native/src/widget/container.rs | 17 +++++---- native/src/widget/pane_grid.rs | 49 +++++++++++++------------ native/src/widget/pick_list.rs | 16 +++++---- native/src/widget/progress_bar.rs | 36 ++++++++++--------- native/src/widget/radio.rs | 44 ++++++++++++----------- native/src/widget/rule.rs | 19 +++++----- native/src/widget/scrollable.rs | 36 ++++++++++--------- native/src/widget/slider.rs | 75 ++++++++++++++++++++------------------ native/src/widget/text.rs | 10 ++++++ native/src/widget/text_input.rs | 76 ++++++++++++++++++++------------------- native/src/widget/toggler.rs | 36 +++++++++++-------- 13 files changed, 261 insertions(+), 207 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 0d9eeebd..1d785f35 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -293,28 +293,32 @@ where if styling.background.is_some() || styling.border_width > 0.0 { if styling.shadow_offset != Vector::default() { // TODO: Implement proper shadow support - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - x: bounds.x + styling.shadow_offset.x, - y: bounds.y + styling.shadow_offset.y, - ..bounds + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x + styling.shadow_offset.x, + y: bounds.y + styling.shadow_offset.y, + ..bounds + }, + border_radius: styling.border_radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color([0.0, 0.0, 0.0, 0.5].into()), - border_radius: styling.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); + Background::Color([0.0, 0.0, 0.0, 0.5].into()), + ); } - renderer.fill_rectangle(renderer::Quad { - bounds, - background: styling + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: styling.border_radius, + border_width: styling.border_width, + border_color: styling.border_color, + }, + styling .background .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: styling.border_radius, - border_width: styling.border_width, - border_color: styling.border_color, - }); + ); } self.content.draw( diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 04f62cd9..0d4a43ec 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -226,13 +226,15 @@ where self.style_sheet.active(self.is_checked) }; - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style.background, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }, + style.background, + ); if self.is_checked { renderer.fill_text(text::Text { diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 9e3d0193..596af7fd 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -238,6 +238,7 @@ where } } +/// Draws the background of a [`Container`] given its [`Style`] and its `bounds`. pub fn draw_background( renderer: &mut Renderer, style: &Style, @@ -246,15 +247,17 @@ pub fn draw_background( Renderer: crate::Renderer, { if style.background.is_some() || style.border_width > 0.0 { - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }, + style .background .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); + ); } } diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index d98369e4..20616ed4 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -609,31 +609,34 @@ where }; if let Some(highlight) = highlight { - renderer.fill_rectangle(renderer::Quad { - bounds: match axis { - Axis::Horizontal => Rectangle { - x: split_region.x, - y: (split_region.y - + (split_region.height - highlight.width) - / 2.0) - .round(), - width: split_region.width, - height: highlight.width, - }, - Axis::Vertical => Rectangle { - x: (split_region.x - + (split_region.width - highlight.width) / 2.0) - .round(), - y: split_region.y, - width: highlight.width, - height: split_region.height, + renderer.fill_quad( + renderer::Quad { + bounds: match axis { + Axis::Horizontal => Rectangle { + x: split_region.x, + y: (split_region.y + + (split_region.height - highlight.width) + / 2.0) + .round(), + width: split_region.width, + height: highlight.width, + }, + Axis::Vertical => Rectangle { + x: (split_region.x + + (split_region.width - highlight.width) + / 2.0) + .round(), + y: split_region.y, + width: highlight.width, + height: split_region.height, + }, }, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: highlight.color.into(), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); + highlight.color, + ); } } } diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index a7fef37b..9d1a86ec 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -360,13 +360,15 @@ where self.style_sheet.active() }; - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style.background, - border_color: style.border_color, - border_width: style.border_width, - border_radius: style.border_radius, - }); + renderer.fill_quad( + renderer::Quad { + bounds, + border_color: style.border_color, + border_width: style.border_width, + border_radius: style.border_radius, + }, + style.background, + ); renderer.fill_text(Text { content: &Renderer::ARROW_DOWN_ICON.to_string(), diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 1f83de10..69eb8c09 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -116,25 +116,29 @@ where let style = self.style_sheet.style(); - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { ..bounds }, - background: style.background, - border_radius: style.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); - - if active_progress_width > 0.0 { - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - width: active_progress_width, - ..bounds - }, - background: style.bar, + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { ..bounds }, border_radius: style.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, - }); + }, + style.background, + ); + + if active_progress_width > 0.0 { + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + width: active_progress_width, + ..bounds + }, + border_radius: style.border_radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + style.bar, + ); } } diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 7d39c526..86ad4c4e 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -10,8 +10,8 @@ use crate::text; use crate::touch; use crate::widget::{self, Row, Text}; use crate::{ - Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, - Point, Rectangle, Widget, + Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, + Rectangle, Widget, }; pub use iced_style::radio::{Style, StyleSheet}; @@ -243,27 +243,31 @@ where self.style_sheet.active() }; - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style.background, - border_radius: size / 2.0, - border_width: style.border_width, - border_color: style.border_color, - }); + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: size / 2.0, + border_width: style.border_width, + border_color: style.border_color, + }, + style.background, + ); if self.is_selected { - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - x: bounds.x + dot_size / 2.0, - y: bounds.y + dot_size / 2.0, - width: bounds.width - dot_size, - height: bounds.height - dot_size, + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x + dot_size / 2.0, + y: bounds.y + dot_size / 2.0, + width: bounds.width - dot_size, + height: bounds.height - dot_size, + }, + border_radius: dot_size / 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color(style.dot_color), - border_radius: dot_size / 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); + style.dot_color, + ); } } diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 8f4e66a6..7c8c5dbc 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -2,8 +2,7 @@ use crate::layout; use crate::renderer; use crate::{ - Background, Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, - Widget, + Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, }; use std::hash::Hash; @@ -113,13 +112,15 @@ where } }; - renderer.fill_rectangle(renderer::Quad { - bounds, - background: Background::Color(style.color), - border_radius: style.radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: style.radius, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + style.color, + ); } fn hash_layout(&self, state: &mut Hasher) { diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 00f80bc6..2bf2ea5e 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -526,28 +526,32 @@ where }, |renderer| { if is_scrollbar_visible { - renderer.fill_rectangle(renderer::Quad { - bounds: scrollbar.bounds, - background: style.background.unwrap_or( - Background::Color(Color::TRANSPARENT), - ), - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); + renderer.fill_quad( + renderer::Quad { + bounds: scrollbar.bounds, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }, + style.background.unwrap_or(Background::Color( + Color::TRANSPARENT, + )), + ); } if is_mouse_over || self.state.is_scroller_grabbed() || is_scrollbar_visible { - renderer.fill_rectangle(renderer::Quad { - bounds: scrollbar.scroller.bounds, - background: Background::Color(style.scroller.color), - border_radius: style.scroller.border_radius, - border_width: style.scroller.border_width, - border_color: style.scroller.border_color, - }); + renderer.fill_quad( + renderer::Quad { + bounds: scrollbar.scroller.bounds, + border_radius: style.scroller.border_radius, + border_width: style.scroller.border_width, + border_color: style.scroller.border_color, + }, + style.scroller.color, + ); } }, ); diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 01053081..49bafab4 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -58,6 +58,7 @@ where T: Copy + From + std::cmp::PartialOrd, Message: Clone, { + /// The default height of a [`Slider`]. pub const DEFAULT_HEIGHT: u16 = 22; /// Creates a new [`Slider`]. @@ -272,31 +273,35 @@ where let rail_y = bounds.y + (bounds.height / 2.0).round(); - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - x: bounds.x, - y: rail_y, - width: bounds.width, - height: 2.0, + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: rail_y, + width: bounds.width, + height: 2.0, + }, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color(style.rail_colors.0), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); - - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - x: bounds.x, - y: rail_y + 2.0, - width: bounds.width, - height: 2.0, + style.rail_colors.0, + ); + + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: rail_y + 2.0, + width: bounds.width, + height: 2.0, + }, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color(style.rail_colors.1), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }); + Background::Color(style.rail_colors.1), + ); let (handle_width, handle_height, handle_border_radius) = match style .handle @@ -325,18 +330,20 @@ where / (range_end - range_start) }; - renderer.fill_rectangle(renderer::Quad { - bounds: Rectangle { - x: bounds.x + handle_offset.round(), - y: rail_y - handle_height / 2.0, - width: handle_width, - height: handle_height, + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x + handle_offset.round(), + y: rail_y - handle_height / 2.0, + width: handle_width, + height: handle_height, + }, + border_radius: handle_border_radius, + border_width: style.handle.border_width, + border_color: style.handle.border_color, }, - background: Background::Color(style.handle.color), - border_radius: handle_border_radius, - border_width: style.handle.border_width, - border_color: style.handle.border_color, - }); + style.handle.color, + ); } fn mouse_interaction( diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 79688b28..4dbc4a65 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -163,6 +163,16 @@ where } } +/// Draws text using the same logic as the [`Text`] widget. +/// +/// Specifically: +/// +/// * If no `size` is provided, the default text size of the `Renderer` will be +/// used. +/// * If no `color` is provided, the [`renderer::Style::text_color`] will be +/// used. +/// * The alignment attributes do not affect the position of the bounds of the +/// [`Layout`]. pub fn draw( renderer: &mut Renderer, style: &renderer::Style, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index db60b553..40c6c573 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -20,8 +20,8 @@ use crate::renderer; use crate::text::{self, Text}; use crate::touch; use crate::{ - Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, - Point, Rectangle, Size, Vector, Widget, + Clipboard, Color, Element, Hasher, Layout, Length, Padding, Point, + Rectangle, Size, Vector, Widget, }; use std::u32; @@ -196,13 +196,15 @@ where self.style_sheet.active() }; - renderer.fill_rectangle(renderer::Quad { - bounds, - background: style.background, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }); + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: style.border_radius, + border_width: style.border_width, + border_color: style.border_color, + }, + style.background, + ); let text = value.to_string(); let size = self.size.unwrap_or(renderer.default_size()); @@ -221,20 +223,20 @@ where ); ( - Some(renderer::Quad { - bounds: Rectangle { - x: text_bounds.x + text_value_width, - y: text_bounds.y, - width: 1.0, - height: text_bounds.height, + Some(( + renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + text_value_width, + y: text_bounds.y, + width: 1.0, + height: text_bounds.height, + }, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color( - self.style_sheet.value_color(), - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }), + self.style_sheet.value_color(), + )), offset, ) } @@ -265,20 +267,20 @@ where let width = right_position - left_position; ( - Some(renderer::Quad { - bounds: Rectangle { - x: text_bounds.x + left_position, - y: text_bounds.y, - width, - height: text_bounds.height, + Some(( + renderer::Quad { + bounds: Rectangle { + x: text_bounds.x + left_position, + y: text_bounds.y, + width, + height: text_bounds.height, + }, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - background: Background::Color( - self.style_sheet.selection_color(), - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }), + self.style_sheet.selection_color(), + )), if end == right { right_offset } else { @@ -302,8 +304,8 @@ where ); let render = |renderer: &mut Renderer| { - if let Some(cursor) = cursor { - renderer.fill_rectangle(cursor); + if let Some((cursor, color)) = cursor { + renderer.fill_quad(cursor, color); } renderer.fill_text(Text { diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 78e3d5ef..2dcc3ffe 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -258,13 +258,17 @@ where height: bounds.height - (2.0 * space), }; - renderer.fill_rectangle(renderer::Quad { - bounds: toggler_background_bounds, - background: style.background.into(), - border_radius, - border_width: 1.0, - border_color: style.background_border.unwrap_or(style.background), - }); + renderer.fill_quad( + renderer::Quad { + bounds: toggler_background_bounds, + border_radius, + border_width: 1.0, + border_color: style + .background_border + .unwrap_or(style.background), + }, + style.background, + ); let toggler_foreground_bounds = Rectangle { x: bounds.x @@ -278,13 +282,17 @@ where height: bounds.height - (4.0 * space), }; - renderer.fill_rectangle(renderer::Quad { - bounds: toggler_foreground_bounds, - background: style.foreground.into(), - border_radius, - border_width: 1.0, - border_color: style.foreground_border.unwrap_or(style.foreground), - }); + renderer.fill_quad( + renderer::Quad { + bounds: toggler_foreground_bounds, + border_radius, + border_width: 1.0, + border_color: style + .foreground_border + .unwrap_or(style.foreground), + }, + style.foreground, + ); } fn hash_layout(&self, state: &mut Hasher) { -- cgit