From 6ce12fc0c60adbd169676ee985e8529831633a76 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 3 Oct 2022 15:53:39 -0700 Subject: Use `Cow<'static, [u8]>` in image/svg, add constructors taking &[u8]` This should resolve https://github.com/iced-rs/iced/issues/580 by providing a way to use an image included with `include_bytes!` without needing to copy it to a `Vec` to create an image handle. It would be nice if these methods could also be `const`, but that isn't possible due to the hashing being done. This is technically a breaking change since `Handle::data()` is public. But if that is used, it's most likely in used somewhere that only relies on the type derefing to `&[u8]`. --- native/src/image.rs | 31 +++++++++++++++++++++++++++---- native/src/svg.rs | 12 ++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) (limited to 'native') diff --git a/native/src/image.rs b/native/src/image.rs index 516eb2db..41e41aa4 100644 --- a/native/src/image.rs +++ b/native/src/image.rs @@ -1,6 +1,7 @@ //! Load and draw raster graphics. use crate::{Hasher, Rectangle}; +use std::borrow::Cow; use std::hash::{Hash, Hasher as _}; use std::path::PathBuf; use std::sync::Arc; @@ -29,7 +30,22 @@ impl Handle { Self::from_data(Data::Pixels { width, height, - pixels, + pixels: Cow::Owned(pixels), + }) + } + + /// Like [`Handle::from_pixels`], but from static pixel data. + /// + /// Useful for images included in binary, for instance with [`include_bytes!`]. + pub fn from_static_pixels( + width: u32, + height: u32, + pixels: &'static [u8], + ) -> Handle { + Self::from_data(Data::Pixels { + width, + height, + pixels: Cow::Borrowed(pixels), }) } @@ -40,7 +56,14 @@ impl Handle { /// 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)) + Self::from_data(Data::Bytes(Cow::Owned(bytes))) + } + + /// Like [`Handle::from_memory`], but from static image data. + /// + /// Useful for images included in binary, for instance with [`include_bytes!`]. + pub fn from_static_memory(bytes: &'static [u8]) -> Handle { + Self::from_data(Data::Bytes(Cow::Borrowed(bytes))) } fn from_data(data: Data) -> Handle { @@ -86,7 +109,7 @@ pub enum Data { Path(PathBuf), /// In-memory data - Bytes(Vec), + Bytes(Cow<'static, [u8]>), /// Decoded image pixels in BGRA format. Pixels { @@ -95,7 +118,7 @@ pub enum Data { /// The height of the image. height: u32, /// The pixels. - pixels: Vec, + pixels: Cow<'static, [u8]>, }, } diff --git a/native/src/svg.rs b/native/src/svg.rs index f86fec5b..c89eed3f 100644 --- a/native/src/svg.rs +++ b/native/src/svg.rs @@ -1,6 +1,7 @@ //! Load and draw vector graphics. use crate::{Hasher, Rectangle}; +use std::borrow::Cow; use std::hash::{Hash, Hasher as _}; use std::path::PathBuf; use std::sync::Arc; @@ -25,7 +26,14 @@ impl Handle { /// 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())) + Self::from_data(Data::Bytes(Cow::Owned(bytes.into()))) + } + + /// Like [`Handle::from_memory`], but from static image data. + /// + /// Useful for images included in binary, for instance with [`include_bytes!`]. + pub fn from_static_memory(bytes: &'static [u8]) -> Handle { + Self::from_data(Data::Bytes(Cow::Borrowed(bytes))) } fn from_data(data: Data) -> Handle { @@ -64,7 +72,7 @@ pub enum Data { /// In-memory data /// /// Can contain an SVG string or a gzip compressed data. - Bytes(Vec), + Bytes(Cow<'static, [u8]>), } impl std::fmt::Debug for Data { -- cgit From 7ea7dbef578ddbe2a9a50da6aab253ba016f1362 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Thu, 6 Oct 2022 20:38:21 +0200 Subject: feat: Add window drag support from winit Exposes access to the winit window's window_drag method as an action. --- native/src/window/action.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'native') diff --git a/native/src/window/action.rs b/native/src/window/action.rs index 73338e22..ce125144 100644 --- a/native/src/window/action.rs +++ b/native/src/window/action.rs @@ -5,6 +5,12 @@ use std::fmt; /// An operation to be performed on some window. pub enum Action { + /// Moves the window with the left mouse button until the button is + /// released. + /// + /// There’s no guarantee that this will work unless the left mouse + /// button was pressed immediately before this function is called. + Drag, /// Resize the window. Resize { /// The new logical width of the window @@ -37,6 +43,7 @@ impl Action { T: 'static, { match self { + Self::Drag => Action::Drag, Self::Resize { width, height } => Action::Resize { width, height }, Self::Move { x, y } => Action::Move { x, y }, Self::SetMode(mode) => Action::SetMode(mode), @@ -48,6 +55,7 @@ impl Action { impl fmt::Debug for Action { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + Self::Drag => write!(f, "Action::Drag"), Self::Resize { width, height } => write!( f, "Action::Resize {{ widget: {}, height: {} }}", -- cgit From 8a50836ffc32a6d9157eb18740b3947c4dbd7d1f Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Sun, 9 Oct 2022 16:35:28 +0200 Subject: feat: Add window maximize support --- native/src/window/action.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'native') diff --git a/native/src/window/action.rs b/native/src/window/action.rs index ce125144..c49fdf9d 100644 --- a/native/src/window/action.rs +++ b/native/src/window/action.rs @@ -18,6 +18,8 @@ pub enum Action { /// The new logical height of the window height: u32, }, + /// Sets the window to maximized or back + Maximize(bool), /// Move the window. /// /// Unsupported on Wayland. @@ -29,6 +31,8 @@ pub enum Action { }, /// Set the [`Mode`] of the window. SetMode(Mode), + /// Sets the window to maximized or back + ToggleMaximize, /// Fetch the current [`Mode`] of the window. FetchMode(Box T + 'static>), } @@ -45,8 +49,10 @@ impl Action { match self { Self::Drag => Action::Drag, Self::Resize { width, height } => Action::Resize { width, height }, + Self::Maximize(bool) => Action::Maximize(bool), Self::Move { x, y } => Action::Move { x, y }, Self::SetMode(mode) => Action::SetMode(mode), + Self::ToggleMaximize => Action::ToggleMaximize, Self::FetchMode(o) => Action::FetchMode(Box::new(move |s| f(o(s)))), } } @@ -61,10 +67,12 @@ impl fmt::Debug for Action { "Action::Resize {{ widget: {}, height: {} }}", width, height ), + Self::Maximize(value) => write!(f, "Action::Maximize({})", value), Self::Move { x, y } => { write!(f, "Action::Move {{ x: {}, y: {} }}", x, y) } Self::SetMode(mode) => write!(f, "Action::SetMode({:?})", mode), + Self::ToggleMaximize => write!(f, "Action::ToggleMaximize"), Self::FetchMode(_) => write!(f, "Action::FetchMode"), } } -- cgit From ac6e137be3e9d2d2a1d8c1284880096a0e2c2a47 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 11 Oct 2022 15:24:26 +0200 Subject: feat: Add window minimize support --- native/src/window/action.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'native') diff --git a/native/src/window/action.rs b/native/src/window/action.rs index c49fdf9d..009dcc27 100644 --- a/native/src/window/action.rs +++ b/native/src/window/action.rs @@ -20,6 +20,8 @@ pub enum Action { }, /// Sets the window to maximized or back Maximize(bool), + /// Set the window to minimized or back + Minimize(bool), /// Move the window. /// /// Unsupported on Wayland. @@ -50,6 +52,7 @@ impl Action { Self::Drag => Action::Drag, Self::Resize { width, height } => Action::Resize { width, height }, Self::Maximize(bool) => Action::Maximize(bool), + Self::Minimize(bool) => Action::Minimize(bool), Self::Move { x, y } => Action::Move { x, y }, Self::SetMode(mode) => Action::SetMode(mode), Self::ToggleMaximize => Action::ToggleMaximize, @@ -68,6 +71,7 @@ impl fmt::Debug for Action { width, height ), Self::Maximize(value) => write!(f, "Action::Maximize({})", value), + Self::Minimize(value) => write!(f, "Action::Minimize({}", value), Self::Move { x, y } => { write!(f, "Action::Move {{ x: {}, y: {} }}", x, y) } -- cgit From 2c103f8654943c773b6de3c70eb2927e92219422 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 27 Oct 2022 11:48:42 -0700 Subject: Constrain padding to inner & outer sizes --- native/src/widget/button.rs | 9 ++++++--- native/src/widget/container.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'native') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 6c0b8f6e..e927998c 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -426,12 +426,15 @@ pub fn layout( padding: Padding, layout_content: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node, ) -> layout::Node { - let limits = limits.width(width).height(height).pad(padding); + let limits = limits.width(width).height(height); + + let mut content = layout_content(renderer, &limits.pad(padding)); + + let padding = padding.constrain(content.size(), limits.max()); - let mut content = layout_content(renderer, &limits); content.move_to(Point::new(padding.left.into(), padding.top.into())); - let size = limits.resolve(content.size()).pad(padding); + let size = limits.pad(padding).resolve(content.size()).pad(padding); layout::Node::with_children(size, vec![content]) } diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 2afad3f2..cc886dcb 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -293,11 +293,13 @@ pub fn layout( .max_width(max_width) .max_height(max_height) .width(width) - .height(height) - .pad(padding); + .height(height); - let mut content = layout_content(renderer, &limits.loose()); - let size = limits.resolve(content.size()); + let mut content = layout_content(renderer, &limits.pad(padding).loose()); + + let padding = padding.constrain(content.size(), limits.max()); + + let size = limits.pad(padding).resolve(content.size()); content.move_to(Point::new(padding.left.into(), padding.top.into())); content.align( -- cgit From ea4b3cd6aeb3c4dcb5113389c85f577fd3714682 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 27 Oct 2022 12:10:47 -0700 Subject: Fix text input padding --- native/src/widget/text_input.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index c2d25520..6ac4a2dd 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -350,15 +350,21 @@ where { let text_size = size.unwrap_or_else(|| renderer.default_size()); - let limits = limits + let text_limits = limits .pad(padding) .width(width) .height(Length::Units(text_size)); + let limits = limits.width(width).height(Length::Shrink); + + let mut text = layout::Node::new(text_limits.resolve(Size::ZERO)); + + let padding = padding.constrain(text.size(), limits.max()); - let mut text = layout::Node::new(limits.resolve(Size::ZERO)); text.move_to(Point::new(padding.left.into(), padding.top.into())); - layout::Node::with_children(text.size().pad(padding), vec![text]) + let size = limits.pad(padding).resolve(text.size()).pad(padding); + + layout::Node::with_children(size, vec![text]) } /// Processes an [`Event`] and updates the [`State`] of a [`TextInput`] -- cgit From b761ab5e1d4ceaae6ac12c28f45dfcd84c76c329 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Wed, 2 Nov 2022 16:49:18 -0700 Subject: Add maximize / restore to PaneGrid --- native/src/widget/pane_grid.rs | 129 ++++++++++++++++++++++++++--------- native/src/widget/pane_grid/state.rs | 54 ++++++++------- 2 files changed, 128 insertions(+), 55 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 96cf78ef..1b55537f 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -101,7 +101,7 @@ where Renderer::Theme: StyleSheet + container::StyleSheet, { state: &'a state::Internal, - elements: Vec<(Pane, Content<'a, Message, Renderer>)>, + elements: Elements>, width: Length, height: Length, spacing: u16, @@ -119,17 +119,30 @@ where /// Creates a [`PaneGrid`] with the given [`State`] and view function. /// /// The view function will be called to display each [`Pane`] present in the - /// [`State`]. + /// [`State`]. [`bool`] is set if the pane is maximized. pub fn new( state: &'a State, - view: impl Fn(Pane, &'a T) -> Content<'a, Message, Renderer>, + view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>, ) -> Self { - let elements = { - state - .panes - .iter() - .map(|(pane, pane_state)| (*pane, view(*pane, pane_state))) - .collect() + let elements = if let Some((pane, pane_state)) = + state.maximized.and_then(|pane| { + state.panes.get(&pane).map(|pane_state| (pane, pane_state)) + }) { + Elements::Maximized( + pane, + view(pane, pane_state, true), + Node::Pane(pane), + ) + } else { + Elements::Normal( + state + .panes + .iter() + .map(|(pane, pane_state)| { + (*pane, view(*pane, pane_state, false)) + }) + .collect(), + ) }; Self { @@ -232,11 +245,18 @@ where } fn diff(&self, tree: &mut Tree) { - tree.diff_children_custom( - &self.elements, - |state, (_, content)| content.diff(state), - |(_, content)| content.state(), - ) + match &self.elements { + Elements::Normal(elements) => tree.diff_children_custom( + elements, + |state, (_, content)| content.diff(state), + |(_, content)| content.state(), + ), + Elements::Maximized(_, content, _) => tree.diff_children_custom( + &[content], + |state, content| content.diff(state), + |content| content.state(), + ), + } } fn width(&self) -> Length { @@ -255,11 +275,11 @@ where layout( renderer, limits, - self.state, + self.elements.node(self.state), self.width, self.height, self.spacing, - self.elements.iter().map(|(pane, content)| (*pane, content)), + self.elements.iter(), |element, renderer, limits| element.layout(renderer, limits), ) } @@ -278,13 +298,13 @@ where let event_status = update( action, - self.state, + self.elements.node(self.state), &event, layout, cursor_position, shell, self.spacing, - self.elements.iter().map(|(pane, content)| (*pane, content)), + self.elements.iter(), &self.on_click, &self.on_drag, &self.on_resize, @@ -297,7 +317,7 @@ where .zip(&mut tree.children) .zip(layout.children()) .map(|(((pane, content), tree), layout)| { - let is_picked = picked_pane == Some(*pane); + let is_picked = picked_pane == Some(pane); content.on_event( tree, @@ -323,7 +343,7 @@ where ) -> mouse::Interaction { mouse_interaction( tree.state.downcast_ref(), - self.state, + self.elements.node(self.state), layout, cursor_position, self.spacing, @@ -361,7 +381,7 @@ where ) { draw( tree.state.downcast_ref(), - self.state, + self.elements.node(self.state), layout, cursor_position, renderer, @@ -374,7 +394,7 @@ where self.elements .iter() .zip(&tree.children) - .map(|((pane, content), tree)| (*pane, (content, tree))), + .map(|((pane, content), tree)| (pane, (content, tree))), |(content, tree), renderer, style, @@ -429,7 +449,7 @@ where pub fn layout( renderer: &Renderer, limits: &layout::Limits, - state: &state::Internal, + node: &Node, width: Length, height: Length, spacing: u16, @@ -439,7 +459,7 @@ pub fn layout( let limits = limits.width(width).height(height); let size = limits.resolve(Size::ZERO); - let regions = state.pane_regions(f32::from(spacing), size); + let regions = node.pane_regions(f32::from(spacing), size); let children = elements .filter_map(|(pane, element)| { let region = regions.get(&pane)?; @@ -464,7 +484,7 @@ pub fn layout( /// accordingly. pub fn update<'a, Message, T: Draggable>( action: &mut state::Action, - state: &state::Internal, + node: &Node, event: &Event, layout: Layout<'_>, cursor_position: Point, @@ -492,7 +512,7 @@ pub fn update<'a, Message, T: Draggable>( cursor_position.y - bounds.y, ); - let splits = state.split_regions( + let splits = node.split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -570,7 +590,7 @@ pub fn update<'a, Message, T: Draggable>( if let Some((split, _)) = action.picked_split() { let bounds = layout.bounds(); - let splits = state.split_regions( + let splits = node.split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -642,7 +662,7 @@ fn click_pane<'a, Message, T>( /// Returns the current [`mouse::Interaction`] of a [`PaneGrid`]. pub fn mouse_interaction( action: &state::Action, - state: &state::Internal, + node: &Node, layout: Layout<'_>, cursor_position: Point, spacing: u16, @@ -658,7 +678,7 @@ pub fn mouse_interaction( let bounds = layout.bounds(); let splits = - state.split_regions(f32::from(spacing), bounds.size()); + node.split_regions(f32::from(spacing), bounds.size()); let relative_cursor = Point::new( cursor_position.x - bounds.x, @@ -687,7 +707,7 @@ pub fn mouse_interaction( /// Draws a [`PaneGrid`]. pub fn draw( action: &state::Action, - state: &state::Internal, + node: &Node, layout: Layout<'_>, cursor_position: Point, renderer: &mut Renderer, @@ -717,7 +737,7 @@ pub fn draw( .and_then(|(split, axis)| { let bounds = layout.bounds(); - let splits = state.split_regions(f32::from(spacing), bounds.size()); + let splits = node.split_regions(f32::from(spacing), bounds.size()); let (_axis, region, ratio) = splits.get(&split)?; @@ -736,7 +756,7 @@ pub fn draw( ); let splits = - state.split_regions(f32::from(spacing), bounds.size()); + node.split_regions(f32::from(spacing), bounds.size()); let (_split, axis, region) = hovered_split( splits.iter(), @@ -897,3 +917,48 @@ fn hovered_split<'a>( }) .next() } + +/// TODO +#[derive(Debug)] +pub enum Elements { + /// TODO + Normal(Vec<(Pane, T)>), + /// TODO + Maximized(Pane, T, Node), +} + +impl Elements { + /// TODO + pub fn iter(&self) -> Box + '_> { + match self { + Elements::Normal(elements) => Box::new( + elements.iter().map(|(pane, content)| (*pane, content)), + ), + Elements::Maximized(pane, content, _) => { + Box::new(std::iter::once((*pane, content))) + } + } + } + + /// TODO + pub fn iter_mut( + &mut self, + ) -> Box + '_> { + match self { + Elements::Normal(elements) => Box::new( + elements.iter_mut().map(|(pane, content)| (*pane, content)), + ), + Elements::Maximized(pane, content, _) => { + Box::new(std::iter::once((*pane, content))) + } + } + } + + /// TODO + pub fn node<'a>(&'a self, state: &'a state::Internal) -> &'a Node { + match self { + Elements::Normal(_) => state.layout(), + Elements::Maximized(_, _, node) => node, + } + } +} diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index cdca6267..92d26f5a 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -4,9 +4,9 @@ use crate::widget::pane_grid::{ Axis, Configuration, Direction, Node, Pane, Split, }; -use crate::{Point, Rectangle, Size}; +use crate::{Point, Size}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; /// The state of a [`PaneGrid`]. /// @@ -31,6 +31,9 @@ pub struct State { /// /// [`PaneGrid`]: crate::widget::PaneGrid pub internal: Internal, + + /// The maximized [`Pane`] of the [`PaneGrid`] + pub(super) maximized: Option, } impl State { @@ -52,7 +55,11 @@ impl State { let internal = Internal::from_configuration(&mut panes, config.into(), 0); - State { panes, internal } + State { + panes, + internal, + maximized: None, + } } /// Returns the total amount of panes in the [`State`]. @@ -194,12 +201,28 @@ impl State { /// Closes the given [`Pane`] and returns its internal state and its closest /// sibling, if it exists. pub fn close(&mut self, pane: &Pane) -> Option<(T, Pane)> { + if self.maximized == Some(*pane) { + let _ = self.maximized.take(); + } + if let Some(sibling) = self.internal.layout.remove(pane) { self.panes.remove(pane).map(|state| (state, sibling)) } else { None } } + + /// Maximize the given [`Pane`]. Only this pane will be rendered by the + /// [`PaneGrid`] until [`Self::restore()`] is called. + pub fn maximize(&mut self, pane: &Pane) { + self.maximized = Some(*pane); + } + + /// Restore the currently maximized [`Pane`] to it's normal size. All panes + /// will be rendered by the [`PaneGrid`] + pub fn restore(&mut self) { + let _ = self.maximized.take(); + } } /// The internal state of a [`PaneGrid`]. @@ -226,11 +249,13 @@ impl Internal { let Internal { layout: a, last_id: next_id, + .. } = Self::from_configuration(panes, *a, next_id); let Internal { layout: b, last_id: next_id, + .. } = Self::from_configuration(panes, *b, next_id); ( @@ -304,25 +329,8 @@ impl Action { } impl Internal { - /// Calculates the current [`Pane`] regions from the [`PaneGrid`] layout. - /// - /// [`PaneGrid`]: crate::widget::PaneGrid - pub fn pane_regions( - &self, - spacing: f32, - size: Size, - ) -> BTreeMap { - self.layout.pane_regions(spacing, size) - } - - /// Calculates the current [`Split`] regions from the [`PaneGrid`] layout. - /// - /// [`PaneGrid`]: crate::widget::PaneGrid - pub fn split_regions( - &self, - spacing: f32, - size: Size, - ) -> BTreeMap { - self.layout.split_regions(spacing, size) + /// The layout [`Node`] of the [`Internal`] state + pub fn layout(&self) -> &Node { + &self.layout } } -- cgit From df7bf55ce162c5523f530a43113194a6c064a220 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Wed, 2 Nov 2022 17:12:38 -0700 Subject: Disable drag when maximized --- native/src/widget/pane_grid.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 1b55537f..a58bfc77 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -221,6 +221,12 @@ where self.style = style.into(); self } + + fn drag_enabled(&self) -> bool { + (!self.elements.is_maximized()) + .then(|| self.on_drag.is_some()) + .unwrap_or_default() + } } impl<'a, Message, Renderer> Widget @@ -296,6 +302,11 @@ where ) -> event::Status { let action = tree.state.downcast_mut::(); + let on_drag = self + .drag_enabled() + .then_some(&self.on_drag) + .unwrap_or(&None); + let event_status = update( action, self.elements.node(self.state), @@ -306,7 +317,7 @@ where self.spacing, self.elements.iter(), &self.on_click, - &self.on_drag, + on_drag, &self.on_resize, ); @@ -361,7 +372,7 @@ where cursor_position, viewport, renderer, - self.on_drag.is_some(), + self.drag_enabled(), ) }) .max() @@ -961,4 +972,9 @@ impl Elements { Elements::Maximized(_, _, node) => node, } } + + /// TODO + pub fn is_maximized(&self) -> bool { + matches!(self, Self::Maximized(..)) + } } -- cgit From 1687d11389fa8ddfb8d2d7cda64cc6b5c4aa7f9c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 02:35:17 +0100 Subject: Increase default `padding` of `TextInput` --- native/src/widget/text_input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index e5213cbe..54a6aaf8 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -92,7 +92,7 @@ where is_secure: false, font: Default::default(), width: Length::Fill, - padding: Padding::ZERO, + padding: Padding::new(5), size: None, on_change: Box::new(on_change), on_paste: None, -- cgit From 923878c7b7404739a3f8f2dd86a2e19802fa86de Mon Sep 17 00:00:00 2001 From: tarkah Date: Wed, 2 Nov 2022 19:00:07 -0700 Subject: Fix tests & lints --- native/src/widget/pane_grid.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index a58bfc77..94ef84a3 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -85,7 +85,7 @@ use crate::{ /// let (mut state, _) = pane_grid::State::new(PaneState::SomePane); /// /// let pane_grid = -/// PaneGrid::new(&state, |pane, state| { +/// PaneGrid::new(&state, |pane, state, is_maximized| { /// pane_grid::Content::new(match state { /// PaneState::SomePane => text("This is some pane"), /// PaneState::AnotherKindOfPane => text("This is another kind of pane"), @@ -302,10 +302,11 @@ where ) -> event::Status { let action = tree.state.downcast_mut::(); - let on_drag = self - .drag_enabled() - .then_some(&self.on_drag) - .unwrap_or(&None); + let on_drag = if self.drag_enabled() { + &self.on_drag + } else { + &None + }; let event_status = update( action, -- cgit From 988515d57f8c67a22ca0554f3e1327b26e5c6ecf Mon Sep 17 00:00:00 2001 From: tarkah Date: Wed, 2 Nov 2022 19:25:27 -0700 Subject: Add state::Scoped & rename Elements as Contents --- native/src/widget/pane_grid.rs | 176 +++++++++++++++++------------------ native/src/widget/pane_grid/state.rs | 18 +++- 2 files changed, 100 insertions(+), 94 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 94ef84a3..8864da0c 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -100,8 +100,8 @@ where Renderer: crate::Renderer, Renderer::Theme: StyleSheet + container::StyleSheet, { - state: &'a state::Internal, - elements: Elements>, + state: state::Scoped<'a>, + contents: Contents>, width: Length, height: Length, spacing: u16, @@ -124,30 +124,32 @@ where state: &'a State, view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>, ) -> Self { - let elements = if let Some((pane, pane_state)) = + let (contents, state) = if let Some((pane, pane_state)) = state.maximized.and_then(|pane| { state.panes.get(&pane).map(|pane_state| (pane, pane_state)) }) { - Elements::Maximized( - pane, - view(pane, pane_state, true), - Node::Pane(pane), + ( + Contents::Maximized(pane, view(pane, pane_state, true)), + state::Scoped::Maximized(Node::Pane(pane)), ) } else { - Elements::Normal( - state - .panes - .iter() - .map(|(pane, pane_state)| { - (*pane, view(*pane, pane_state, false)) - }) - .collect(), + ( + Contents::All( + state + .panes + .iter() + .map(|(pane, pane_state)| { + (*pane, view(*pane, pane_state, false)) + }) + .collect(), + ), + state::Scoped::All(&state.internal), ) }; Self { - elements, - state: &state.internal, + contents, + state, width: Length::Fill, height: Length::Fill, spacing: 0, @@ -223,7 +225,7 @@ where } fn drag_enabled(&self) -> bool { - (!self.elements.is_maximized()) + (!self.contents.is_maximized()) .then(|| self.on_drag.is_some()) .unwrap_or_default() } @@ -244,20 +246,20 @@ where } fn children(&self) -> Vec { - self.elements + self.contents .iter() .map(|(_, content)| content.state()) .collect() } fn diff(&self, tree: &mut Tree) { - match &self.elements { - Elements::Normal(elements) => tree.diff_children_custom( - elements, + match &self.contents { + Contents::All(contents) => tree.diff_children_custom( + contents, |state, (_, content)| content.diff(state), |(_, content)| content.state(), ), - Elements::Maximized(_, content, _) => tree.diff_children_custom( + Contents::Maximized(_, content) => tree.diff_children_custom( &[content], |state, content| content.diff(state), |content| content.state(), @@ -281,12 +283,12 @@ where layout( renderer, limits, - self.elements.node(self.state), + &self.state, self.width, self.height, self.spacing, - self.elements.iter(), - |element, renderer, limits| element.layout(renderer, limits), + self.contents.iter(), + |content, renderer, limits| content.layout(renderer, limits), ) } @@ -310,13 +312,13 @@ where let event_status = update( action, - self.elements.node(self.state), + &self.state, &event, layout, cursor_position, shell, self.spacing, - self.elements.iter(), + self.contents.iter(), &self.on_click, on_drag, &self.on_resize, @@ -324,7 +326,7 @@ where let picked_pane = action.picked_pane().map(|(pane, _)| pane); - self.elements + self.contents .iter_mut() .zip(&mut tree.children) .zip(layout.children()) @@ -355,14 +357,14 @@ where ) -> mouse::Interaction { mouse_interaction( tree.state.downcast_ref(), - self.elements.node(self.state), + &self.state, layout, cursor_position, self.spacing, self.on_resize.as_ref().map(|(leeway, _)| *leeway), ) .unwrap_or_else(|| { - self.elements + self.contents .iter() .zip(&tree.children) .zip(layout.children()) @@ -393,7 +395,7 @@ where ) { draw( tree.state.downcast_ref(), - self.elements.node(self.state), + &self.state, layout, cursor_position, renderer, @@ -403,7 +405,7 @@ where self.spacing, self.on_resize.as_ref().map(|(leeway, _)| *leeway), self.style, - self.elements + self.contents .iter() .zip(&tree.children) .map(|((pane, content), tree)| (pane, (content, tree))), @@ -432,7 +434,7 @@ where layout: Layout<'_>, renderer: &Renderer, ) -> Option> { - self.elements + self.contents .iter() .zip(&mut tree.children) .zip(layout.children()) @@ -458,27 +460,27 @@ where } /// Calculates the [`Layout`] of a [`PaneGrid`]. -pub fn layout( +pub fn layout<'a, Renderer, T>( renderer: &Renderer, limits: &layout::Limits, - node: &Node, + state: &state::Scoped<'a>, width: Length, height: Length, spacing: u16, - elements: impl Iterator, - layout_element: impl Fn(T, &Renderer, &layout::Limits) -> layout::Node, + contents: impl Iterator, + layout_content: impl Fn(T, &Renderer, &layout::Limits) -> layout::Node, ) -> layout::Node { let limits = limits.width(width).height(height); let size = limits.resolve(Size::ZERO); - let regions = node.pane_regions(f32::from(spacing), size); - let children = elements - .filter_map(|(pane, element)| { + let regions = state.layout().pane_regions(f32::from(spacing), size); + let children = contents + .filter_map(|(pane, content)| { let region = regions.get(&pane)?; let size = Size::new(region.width, region.height); - let mut node = layout_element( - element, + let mut node = layout_content( + content, renderer, &layout::Limits::new(size, size), ); @@ -496,13 +498,13 @@ pub fn layout( /// accordingly. pub fn update<'a, Message, T: Draggable>( action: &mut state::Action, - node: &Node, + state: &state::Scoped<'a>, event: &Event, layout: Layout<'_>, cursor_position: Point, shell: &mut Shell<'_, Message>, spacing: u16, - elements: impl Iterator, + contents: impl Iterator, on_click: &Option Message + 'a>>, on_drag: &Option Message + 'a>>, on_resize: &Option<(u16, Box Message + 'a>)>, @@ -524,7 +526,7 @@ pub fn update<'a, Message, T: Draggable>( cursor_position.y - bounds.y, ); - let splits = node.split_regions( + let splits = state.layout().split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -546,7 +548,7 @@ pub fn update<'a, Message, T: Draggable>( layout, cursor_position, shell, - elements, + contents, on_click, on_drag, ); @@ -558,7 +560,7 @@ pub fn update<'a, Message, T: Draggable>( layout, cursor_position, shell, - elements, + contents, on_click, on_drag, ); @@ -571,7 +573,7 @@ pub fn update<'a, Message, T: Draggable>( | Event::Touch(touch::Event::FingerLost { .. }) => { if let Some((pane, _)) = action.picked_pane() { if let Some(on_drag) = on_drag { - let mut dropped_region = elements + let mut dropped_region = contents .zip(layout.children()) .filter(|(_, layout)| { layout.bounds().contains(cursor_position) @@ -602,7 +604,7 @@ pub fn update<'a, Message, T: Draggable>( if let Some((split, _)) = action.picked_split() { let bounds = layout.bounds(); - let splits = node.split_regions( + let splits = state.layout().split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -641,13 +643,13 @@ fn click_pane<'a, Message, T>( layout: Layout<'_>, cursor_position: Point, shell: &mut Shell<'_, Message>, - elements: impl Iterator, + contents: impl Iterator, on_click: &Option Message + 'a>>, on_drag: &Option Message + 'a>>, ) where T: Draggable, { - let mut clicked_region = elements + let mut clicked_region = contents .zip(layout.children()) .filter(|(_, layout)| layout.bounds().contains(cursor_position)); @@ -672,9 +674,9 @@ fn click_pane<'a, Message, T>( } /// Returns the current [`mouse::Interaction`] of a [`PaneGrid`]. -pub fn mouse_interaction( +pub fn mouse_interaction<'a>( action: &state::Action, - node: &Node, + state: &state::Scoped<'a>, layout: Layout<'_>, cursor_position: Point, spacing: u16, @@ -689,8 +691,9 @@ pub fn mouse_interaction( resize_leeway.and_then(|leeway| { let bounds = layout.bounds(); - let splits = - node.split_regions(f32::from(spacing), bounds.size()); + let splits = state + .layout() + .split_regions(f32::from(spacing), bounds.size()); let relative_cursor = Point::new( cursor_position.x - bounds.x, @@ -717,9 +720,9 @@ pub fn mouse_interaction( } /// Draws a [`PaneGrid`]. -pub fn draw( +pub fn draw<'a, Renderer, T>( action: &state::Action, - node: &Node, + state: &state::Scoped<'a>, layout: Layout<'_>, cursor_position: Point, renderer: &mut Renderer, @@ -729,7 +732,7 @@ pub fn draw( spacing: u16, resize_leeway: Option, style: ::Style, - elements: impl Iterator, + contents: impl Iterator, draw_pane: impl Fn( T, &mut Renderer, @@ -749,7 +752,9 @@ pub fn draw( .and_then(|(split, axis)| { let bounds = layout.bounds(); - let splits = node.split_regions(f32::from(spacing), bounds.size()); + let splits = state + .layout() + .split_regions(f32::from(spacing), bounds.size()); let (_axis, region, ratio) = splits.get(&split)?; @@ -767,8 +772,9 @@ pub fn draw( cursor_position.y - bounds.y, ); - let splits = - node.split_regions(f32::from(spacing), bounds.size()); + let splits = state + .layout() + .split_regions(f32::from(spacing), bounds.size()); let (_split, axis, region) = hovered_split( splits.iter(), @@ -791,7 +797,7 @@ pub fn draw( let mut render_picked_pane = None; - for ((id, pane), layout) in elements.zip(layout.children()) { + for ((id, pane), layout) in contents.zip(layout.children()) { match picked_pane { Some((dragging, origin)) if id == dragging => { render_picked_pane = Some((pane, origin, layout)); @@ -930,52 +936,40 @@ fn hovered_split<'a>( .next() } -/// TODO +/// The visible contents of the [`PaneGrid`] #[derive(Debug)] -pub enum Elements { - /// TODO - Normal(Vec<(Pane, T)>), - /// TODO - Maximized(Pane, T, Node), +pub enum Contents { + /// All panes are visible + All(Vec<(Pane, T)>), + /// A maximized pane is visible + Maximized(Pane, T), } -impl Elements { - /// TODO +impl Contents { + /// Returns an iterator over the values of the [`Contents`] pub fn iter(&self) -> Box + '_> { match self { - Elements::Normal(elements) => Box::new( - elements.iter().map(|(pane, content)| (*pane, content)), + Contents::All(contents) => Box::new( + contents.iter().map(|(pane, content)| (*pane, content)), ), - Elements::Maximized(pane, content, _) => { + Contents::Maximized(pane, content) => { Box::new(std::iter::once((*pane, content))) } } } - /// TODO - pub fn iter_mut( - &mut self, - ) -> Box + '_> { + fn iter_mut(&mut self) -> Box + '_> { match self { - Elements::Normal(elements) => Box::new( - elements.iter_mut().map(|(pane, content)| (*pane, content)), + Contents::All(contents) => Box::new( + contents.iter_mut().map(|(pane, content)| (*pane, content)), ), - Elements::Maximized(pane, content, _) => { + Contents::Maximized(pane, content) => { Box::new(std::iter::once((*pane, content))) } } } - /// TODO - pub fn node<'a>(&'a self, state: &'a state::Internal) -> &'a Node { - match self { - Elements::Normal(_) => state.layout(), - Elements::Maximized(_, _, node) => node, - } - } - - /// TODO - pub fn is_maximized(&self) -> bool { + fn is_maximized(&self) -> bool { matches!(self, Self::Maximized(..)) } } diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index 92d26f5a..b5bebc2e 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -281,6 +281,15 @@ impl Internal { } } +/// The scoped internal state of the [`PaneGrid`] +#[derive(Debug)] +pub enum Scoped<'a> { + /// The state when all panes are visible + All(&'a Internal), + /// The state when a pane is maximized + Maximized(Node), +} + /// The current action of a [`PaneGrid`]. /// /// [`PaneGrid`]: crate::widget::PaneGrid @@ -328,9 +337,12 @@ impl Action { } } -impl Internal { - /// The layout [`Node`] of the [`Internal`] state +impl<'a> Scoped<'a> { + /// The layout [`Node`] of the [`Scope`] state pub fn layout(&self) -> &Node { - &self.layout + match self { + Scoped::All(Internal { layout, .. }) => layout, + Scoped::Maximized(layout) => layout, + } } } -- cgit From 2f6c71d99a2c739c8b86bdf9d024e83ae994042d Mon Sep 17 00:00:00 2001 From: tarkah Date: Wed, 2 Nov 2022 19:54:49 -0700 Subject: Fix doc links --- native/src/widget/pane_grid/state.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index b5bebc2e..70a2aa88 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -214,12 +214,16 @@ impl State { /// Maximize the given [`Pane`]. Only this pane will be rendered by the /// [`PaneGrid`] until [`Self::restore()`] is called. + /// + /// [`PaneGrid`]: crate::widget::PaneGrid pub fn maximize(&mut self, pane: &Pane) { self.maximized = Some(*pane); } /// Restore the currently maximized [`Pane`] to it's normal size. All panes - /// will be rendered by the [`PaneGrid`] + /// will be rendered by the [`PaneGrid`]. + /// + /// [`PaneGrid`]: crate::widget::PaneGrid pub fn restore(&mut self) { let _ = self.maximized.take(); } @@ -282,6 +286,8 @@ impl Internal { } /// The scoped internal state of the [`PaneGrid`] +/// +/// [`PaneGrid`]: crate::widget::PaneGrid #[derive(Debug)] pub enum Scoped<'a> { /// The state when all panes are visible @@ -338,7 +344,7 @@ impl Action { } impl<'a> Scoped<'a> { - /// The layout [`Node`] of the [`Scope`] state + /// The layout [`Node`] of the [`Scoped`] state pub fn layout(&self) -> &Node { match self { Scoped::All(Internal { layout, .. }) => layout, -- cgit From 951fbc83ff8878be03eb6c8c43f2a28d0f0f0d4c Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 3 Nov 2022 08:02:20 -0700 Subject: Remove maximized when split occurs --- native/src/widget/pane_grid/state.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'native') diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index 70a2aa88..882a45f2 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -160,6 +160,7 @@ impl State { node.split(new_split, axis, new_pane); let _ = self.panes.insert(new_pane, state); + let _ = self.maximized.take(); Some((new_pane, new_split)) } -- cgit From 853ff4bcf4eff24808c680f9a35bfc0013cb779d Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 3 Nov 2022 11:32:36 -0700 Subject: Add pub method for getting maximized value --- native/src/widget/pane_grid/state.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'native') diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index 882a45f2..c9e9433d 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -228,6 +228,13 @@ impl State { pub fn restore(&mut self) { let _ = self.maximized.take(); } + + /// Returns the maximized [`Pane`] of the [`PaneGrid`]. + /// + /// [`PaneGrid`]: crate::widget::PaneGrid + pub fn maximized(&self) -> Option { + self.maximized + } } /// The internal state of a [`PaneGrid`]. -- cgit From c0596179bd8582e4f4b5289cdeee8de4fa3de464 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Thu, 3 Nov 2022 00:35:01 +0100 Subject: non uniform border radius for quads --- native/src/element.rs | 2 +- native/src/overlay/menu.rs | 4 ++-- native/src/renderer.rs | 26 +++++++++++++++++++++++++- native/src/widget/button.rs | 4 ++-- native/src/widget/checkbox.rs | 2 +- native/src/widget/container.rs | 2 +- native/src/widget/pane_grid.rs | 2 +- native/src/widget/pick_list.rs | 2 +- native/src/widget/progress_bar.rs | 4 ++-- native/src/widget/radio.rs | 4 ++-- native/src/widget/rule.rs | 2 +- native/src/widget/scrollable.rs | 4 ++-- native/src/widget/slider.rs | 6 +++--- native/src/widget/text_input.rs | 6 +++--- native/src/widget/toggler.rs | 4 ++-- 15 files changed, 49 insertions(+), 25 deletions(-) (limited to 'native') diff --git a/native/src/element.rs b/native/src/element.rs index 074e422e..955e1bee 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -503,7 +503,7 @@ where bounds: layout.bounds(), border_color: color, border_width: 1.0, - border_radius: 0.0, + border_radius: 0.0.into(), }, Color::TRANSPARENT, ); diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index 08135872..dbcf23d4 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -299,7 +299,7 @@ where }, border_color: appearance.border_color, border_width: appearance.border_width, - border_radius: appearance.border_radius, + border_radius: appearance.border_radius.into(), }, appearance.background, ); @@ -491,7 +491,7 @@ where bounds, border_color: Color::TRANSPARENT, border_width: 0.0, - border_radius: appearance.border_radius, + border_radius: appearance.border_radius.into(), }, appearance.selected_background, ); diff --git a/native/src/renderer.rs b/native/src/renderer.rs index ef64ac36..39c1b4c7 100644 --- a/native/src/renderer.rs +++ b/native/src/renderer.rs @@ -50,7 +50,7 @@ pub struct Quad { pub bounds: Rectangle, /// The border radius of the [`Quad`]. - pub border_radius: f32, + pub border_radius: QuadBorderRadius, /// The border width of the [`Quad`]. pub border_width: f32, @@ -59,6 +59,30 @@ pub struct Quad { pub border_color: Color, } +/// The border radi for the corners of a [`Quad`] in the order: +/// top-left, top-right, bottom-right, bottom-left. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct QuadBorderRadius([f32; 4]); + +impl QuadBorderRadius { + /// Convert the corners of the Quad into an array [top_left, top_right, bottom_left, bottom_right]. + pub fn to_array(self) -> [f32; 4] { + self.0 + } +} + +impl From for QuadBorderRadius { + fn from(w: f32) -> Self { + Self([w; 4]) + } +} + +impl From<[f32; 4]> for QuadBorderRadius { + fn from(radi: [f32; 4]) -> Self { + Self(radi) + } +} + /// The styling attributes of a [`Renderer`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Style { diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 6c0b8f6e..14759cfd 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -393,7 +393,7 @@ where y: bounds.y + styling.shadow_offset.y, ..bounds }, - border_radius: styling.border_radius, + border_radius: styling.border_radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -404,7 +404,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: styling.border_radius, + border_radius: styling.border_radius.into(), border_width: styling.border_width, border_color: styling.border_color, }, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index dc3c0bd0..8f30037a 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -236,7 +236,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: custom_style.border_radius, + border_radius: custom_style.border_radius.into(), border_width: custom_style.border_width, border_color: custom_style.border_color, }, diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 2afad3f2..b0c4938a 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -321,7 +321,7 @@ pub fn draw_background( renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius, + border_radius: appearance.border_radius.into(), border_width: appearance.border_width, border_color: appearance.border_color, }, diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 96cf78ef..45090ecf 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -828,7 +828,7 @@ pub fn draw( height: split_region.height, }, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 896f5b35..a92ea655 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -514,7 +514,7 @@ pub fn draw( bounds, border_color: style.border_color, border_width: style.border_width, - border_radius: style.border_radius, + border_radius: style.border_radius.into(), }, style.background, ); diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 8a945433..5f8892fe 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -129,7 +129,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { ..bounds }, - border_radius: style.border_radius, + border_radius: style.border_radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -143,7 +143,7 @@ where width: active_progress_width, ..bounds }, - border_radius: style.border_radius, + border_radius: style.border_radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index cb83f745..10e89870 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -245,7 +245,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: size / 2.0, + border_radius: (size / 2.0).into(), border_width: custom_style.border_width, border_color: custom_style.border_color, }, @@ -261,7 +261,7 @@ where width: bounds.width - dot_size, height: bounds.height - dot_size, }, - border_radius: dot_size / 2.0, + border_radius: (dot_size / 2.0).into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 56f8c80d..1d1c04cf 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -123,7 +123,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: style.radius, + border_radius: style.radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 4ebb07a0..b445e505 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -698,7 +698,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds: scrollbar.bounds, - border_radius: style.border_radius, + border_radius: style.border_radius.into(), border_width: style.border_width, border_color: style.border_color, }, @@ -715,7 +715,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds: scrollbar.scroller.bounds, - border_radius: style.scroller.border_radius, + border_radius: style.scroller.border_radius.into(), border_width: style.scroller.border_width, border_color: style.scroller.border_color, }, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 585d9c35..011454de 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -380,7 +380,7 @@ pub fn draw( width: bounds.width, height: 2.0, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -395,7 +395,7 @@ pub fn draw( width: bounds.width, height: 2.0, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -435,7 +435,7 @@ pub fn draw( width: handle_width, height: handle_height, }, - border_radius: handle_border_radius, + border_radius: handle_border_radius.into(), border_width: style.handle.border_width, border_color: style.handle.border_color, }, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 54a6aaf8..ae0305dc 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -766,7 +766,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius, + border_radius: appearance.border_radius.into(), border_width: appearance.border_width, border_color: appearance.border_color, }, @@ -798,7 +798,7 @@ pub fn draw( width: 1.0, height: text_bounds.height, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -842,7 +842,7 @@ pub fn draw( width, height: text_bounds.height, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index 7893f78c..c5c2d82a 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -278,7 +278,7 @@ where renderer.fill_quad( renderer::Quad { bounds: toggler_background_bounds, - border_radius, + border_radius: border_radius.into(), border_width: 1.0, border_color: style .background_border @@ -302,7 +302,7 @@ where renderer.fill_quad( renderer::Quad { bounds: toggler_foreground_bounds, - border_radius, + border_radius: border_radius.into(), border_width: 1.0, border_color: style .foreground_border -- cgit From bc5986c7c69efd206b900e8d923d3df3a225f6cc Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 01:53:24 +0100 Subject: Unify methods by leveraging `Into` in `image` and `svg` --- native/src/image.rs | 28 +++++----------------------- native/src/svg.rs | 11 ++--------- 2 files changed, 7 insertions(+), 32 deletions(-) (limited to 'native') diff --git a/native/src/image.rs b/native/src/image.rs index 41e41aa4..b849ef84 100644 --- a/native/src/image.rs +++ b/native/src/image.rs @@ -26,26 +26,15 @@ impl Handle { /// 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: Cow::Owned(pixels), - }) - } - - /// Like [`Handle::from_pixels`], but from static pixel data. - /// - /// Useful for images included in binary, for instance with [`include_bytes!`]. - pub fn from_static_pixels( + pub fn from_pixels( width: u32, height: u32, - pixels: &'static [u8], + pixels: impl Into>, ) -> Handle { Self::from_data(Data::Pixels { width, height, - pixels: Cow::Borrowed(pixels), + pixels: pixels.into(), }) } @@ -55,15 +44,8 @@ impl Handle { /// /// 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(Cow::Owned(bytes))) - } - - /// Like [`Handle::from_memory`], but from static image data. - /// - /// Useful for images included in binary, for instance with [`include_bytes!`]. - pub fn from_static_memory(bytes: &'static [u8]) -> Handle { - Self::from_data(Data::Bytes(Cow::Borrowed(bytes))) + pub fn from_memory(bytes: impl Into>) -> Handle { + Self::from_data(Data::Bytes(bytes.into())) } fn from_data(data: Data) -> Handle { diff --git a/native/src/svg.rs b/native/src/svg.rs index c89eed3f..d4d20182 100644 --- a/native/src/svg.rs +++ b/native/src/svg.rs @@ -25,15 +25,8 @@ impl Handle { /// /// 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(Cow::Owned(bytes.into()))) - } - - /// Like [`Handle::from_memory`], but from static image data. - /// - /// Useful for images included in binary, for instance with [`include_bytes!`]. - pub fn from_static_memory(bytes: &'static [u8]) -> Handle { - Self::from_data(Data::Bytes(Cow::Borrowed(bytes))) + pub fn from_memory(bytes: impl Into>) -> Handle { + Self::from_data(Data::Bytes(bytes.into())) } fn from_data(data: Data) -> Handle { -- cgit From 8ce8d374b1e8d1d394a42a5ee2bca8af790f0b71 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:13:04 +0100 Subject: Refactor some `image` traits a bit - Use `Size` were applicable. - Rename `TextureStore` to `image::Storage`. - Rename `TextureStoreEntry` to `image::storage::Entry`. - Wire up `viewport_dimensions` to `iced_glow` for `Svg`. --- native/src/image.rs | 4 ++-- native/src/svg.rs | 4 ++-- native/src/widget/image.rs | 4 ++-- native/src/widget/image/viewer.rs | 4 ++-- native/src/widget/svg.rs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'native') diff --git a/native/src/image.rs b/native/src/image.rs index b849ef84..b313d96d 100644 --- a/native/src/image.rs +++ b/native/src/image.rs @@ -1,5 +1,5 @@ //! Load and draw raster graphics. -use crate::{Hasher, Rectangle}; +use crate::{Hasher, Rectangle, Size}; use std::borrow::Cow; use std::hash::{Hash, Hasher as _}; @@ -126,7 +126,7 @@ pub trait Renderer: crate::Renderer { type Handle: Clone + Hash; /// Returns the dimensions of an image for the given [`Handle`]. - fn dimensions(&self, handle: &Self::Handle) -> (u32, u32); + fn dimensions(&self, handle: &Self::Handle) -> Size; /// Draws an image with the given [`Handle`] and inside the provided /// `bounds`. diff --git a/native/src/svg.rs b/native/src/svg.rs index d4d20182..a8e481d2 100644 --- a/native/src/svg.rs +++ b/native/src/svg.rs @@ -1,5 +1,5 @@ //! Load and draw vector graphics. -use crate::{Hasher, Rectangle}; +use crate::{Hasher, Rectangle, Size}; use std::borrow::Cow; use std::hash::{Hash, Hasher as _}; @@ -82,7 +82,7 @@ impl std::fmt::Debug for Data { /// [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); + fn dimensions(&self, handle: &Handle) -> Size; /// Draws an SVG with the given [`Handle`] and inside the provided `bounds`. fn draw(&mut self, handle: Handle, bounds: Rectangle); diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 91d68e34..8bd8ca1e 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -85,7 +85,7 @@ where { // The raw w/h of the underlying image let image_size = { - let (width, height) = renderer.dimensions(handle); + let Size { width, height } = renderer.dimensions(handle); Size::new(width as f32, height as f32) }; @@ -149,7 +149,7 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { - let (width, height) = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.dimensions(&self.handle); let image_size = Size::new(width as f32, height as f32); let bounds = layout.bounds(); diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index b1fe596c..9c83287e 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -108,7 +108,7 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let (width, height) = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.dimensions(&self.handle); let mut size = limits .width(self.width) @@ -409,7 +409,7 @@ pub fn image_size( where Renderer: image::Renderer, { - let (width, height) = renderer.dimensions(handle); + let Size { width, height } = renderer.dimensions(handle); let (width, height) = { let dimensions = (width as f32, height as f32); diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index aa68bfb8..1015ed0a 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -83,7 +83,7 @@ where limits: &layout::Limits, ) -> layout::Node { // The raw w/h of the underlying image - let (width, height) = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.dimensions(&self.handle); let image_size = Size::new(width as f32, height as f32); // The size to be available to the widget prior to `Shrink`ing @@ -120,7 +120,7 @@ where _cursor_position: Point, _viewport: &Rectangle, ) { - let (width, height) = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.dimensions(&self.handle); let image_size = Size::new(width as f32, height as f32); let bounds = layout.bounds(); -- cgit From 438f97a6d00ad0312e7c84b4c1529968bdfba849 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:18:13 +0100 Subject: Use RGBA texture for `image` and `svg` pipelines --- native/src/image.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'native') diff --git a/native/src/image.rs b/native/src/image.rs index b313d96d..06fd7ae6 100644 --- a/native/src/image.rs +++ b/native/src/image.rs @@ -22,7 +22,7 @@ impl Handle { } /// Creates an image [`Handle`] containing the image pixels directly. This - /// function expects the input data to be provided as a `Vec` of BGRA + /// function expects the input data to be provided as a `Vec` of RGBA /// pixels. /// /// This is useful if you have already decoded your image. @@ -31,7 +31,7 @@ impl Handle { height: u32, pixels: impl Into>, ) -> Handle { - Self::from_data(Data::Pixels { + Self::from_data(Data::Rgba { width, height, pixels: pixels.into(), @@ -93,8 +93,8 @@ pub enum Data { /// In-memory data Bytes(Cow<'static, [u8]>), - /// Decoded image pixels in BGRA format. - Pixels { + /// Decoded image pixels in RGBA format. + Rgba { /// The width of the image. width: u32, /// The height of the image. @@ -109,7 +109,7 @@ impl std::fmt::Debug for Data { match self { Data::Path(path) => write!(f, "Path({:?})", path), Data::Bytes(_) => write!(f, "Bytes(...)"), - Data::Pixels { width, height, .. } => { + Data::Rgba { width, height, .. } => { write!(f, "Pixels({} * {})", width, height) } } -- cgit From 7476663069572adec25161b46c26570f864f736f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 8 Nov 2022 03:56:05 +0100 Subject: Rename `Padding::constrain` to `fit` --- native/src/widget/button.rs | 2 +- native/src/widget/container.rs | 2 +- native/src/widget/text_input.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'native') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index e927998c..01b528ec 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -430,7 +430,7 @@ pub fn layout( let mut content = layout_content(renderer, &limits.pad(padding)); - let padding = padding.constrain(content.size(), limits.max()); + let padding = padding.fit(content.size(), limits.max()); content.move_to(Point::new(padding.left.into(), padding.top.into())); diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index cc886dcb..1c060375 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -297,7 +297,7 @@ pub fn layout( let mut content = layout_content(renderer, &limits.pad(padding).loose()); - let padding = padding.constrain(content.size(), limits.max()); + let padding = padding.fit(content.size(), limits.max()); let size = limits.pad(padding).resolve(content.size()); diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 6ac4a2dd..a71c3b63 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -358,7 +358,7 @@ where let mut text = layout::Node::new(text_limits.resolve(Size::ZERO)); - let padding = padding.constrain(text.size(), limits.max()); + let padding = padding.fit(text.size(), limits.max()); text.move_to(Point::new(padding.left.into(), padding.top.into())); -- cgit From 914f0993428c752937d8db0a70a48f6f6f29c839 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 8 Nov 2022 04:04:01 +0100 Subject: Rearrange `layout` code to improve readability --- native/src/widget/button.rs | 4 +--- native/src/widget/container.rs | 2 -- native/src/widget/text_input.rs | 4 +--- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'native') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 01b528ec..1582188b 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -429,13 +429,11 @@ pub fn layout( let limits = limits.width(width).height(height); let mut content = layout_content(renderer, &limits.pad(padding)); - let padding = padding.fit(content.size(), limits.max()); + let size = limits.pad(padding).resolve(content.size()).pad(padding); content.move_to(Point::new(padding.left.into(), padding.top.into())); - let size = limits.pad(padding).resolve(content.size()).pad(padding); - layout::Node::with_children(size, vec![content]) } diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 1c060375..10a80b58 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -296,9 +296,7 @@ pub fn layout( .height(height); let mut content = layout_content(renderer, &limits.pad(padding).loose()); - let padding = padding.fit(content.size(), limits.max()); - let size = limits.pad(padding).resolve(content.size()); content.move_to(Point::new(padding.left.into(), padding.top.into())); diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index a71c3b63..dfc49a8d 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -357,13 +357,11 @@ where let limits = limits.width(width).height(Length::Shrink); let mut text = layout::Node::new(text_limits.resolve(Size::ZERO)); - let padding = padding.fit(text.size(), limits.max()); + let size = limits.pad(padding).resolve(text.size()).pad(padding); text.move_to(Point::new(padding.left.into(), padding.top.into())); - let size = limits.pad(padding).resolve(text.size()).pad(padding); - layout::Node::with_children(size, vec![text]) } -- cgit From 676d8efe03ebdbeeb95aef96b8097395b788b1ab Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 8 Nov 2022 04:59:34 +0100 Subject: Rename `QuadBorderRadius` to `BorderRadius` --- native/src/renderer.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'native') diff --git a/native/src/renderer.rs b/native/src/renderer.rs index 39c1b4c7..5e776be6 100644 --- a/native/src/renderer.rs +++ b/native/src/renderer.rs @@ -50,7 +50,7 @@ pub struct Quad { pub bounds: Rectangle, /// The border radius of the [`Quad`]. - pub border_radius: QuadBorderRadius, + pub border_radius: BorderRadius, /// The border width of the [`Quad`]. pub border_width: f32, @@ -59,30 +59,29 @@ pub struct Quad { pub border_color: Color, } -/// The border radi for the corners of a [`Quad`] in the order: +/// The border radi for the corners of a graphics primitive in the order: /// top-left, top-right, bottom-right, bottom-left. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct QuadBorderRadius([f32; 4]); - -impl QuadBorderRadius { - /// Convert the corners of the Quad into an array [top_left, top_right, bottom_left, bottom_right]. - pub fn to_array(self) -> [f32; 4] { - self.0 - } -} +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct BorderRadius([f32; 4]); -impl From for QuadBorderRadius { +impl From for BorderRadius { fn from(w: f32) -> Self { Self([w; 4]) } } -impl From<[f32; 4]> for QuadBorderRadius { +impl From<[f32; 4]> for BorderRadius { fn from(radi: [f32; 4]) -> Self { Self(radi) } } +impl From for [f32; 4] { + fn from(radi: BorderRadius) -> Self { + radi.0 + } +} + /// The styling attributes of a [`Renderer`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Style { -- cgit From 7de9d2475dbf4ed93c4248580514901f82a0fc0e Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Tue, 8 Nov 2022 08:49:26 -0800 Subject: Couple layout & content to avoid desync --- native/src/widget/pane_grid.rs | 103 ++++++++++++++++++----------------- native/src/widget/pane_grid/state.rs | 20 +------ 2 files changed, 55 insertions(+), 68 deletions(-) (limited to 'native') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 8864da0c..fd771f8b 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -100,8 +100,7 @@ where Renderer: crate::Renderer, Renderer::Theme: StyleSheet + container::StyleSheet, { - state: state::Scoped<'a>, - contents: Contents>, + contents: Contents<'a, Content<'a, Message, Renderer>>, width: Length, height: Length, spacing: u16, @@ -124,32 +123,30 @@ where state: &'a State, view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>, ) -> Self { - let (contents, state) = if let Some((pane, pane_state)) = + let contents = if let Some((pane, pane_state)) = state.maximized.and_then(|pane| { state.panes.get(&pane).map(|pane_state| (pane, pane_state)) }) { - ( - Contents::Maximized(pane, view(pane, pane_state, true)), - state::Scoped::Maximized(Node::Pane(pane)), + Contents::Maximized( + pane, + view(pane, pane_state, true), + Node::Pane(pane), ) } else { - ( - Contents::All( - state - .panes - .iter() - .map(|(pane, pane_state)| { - (*pane, view(*pane, pane_state, false)) - }) - .collect(), - ), - state::Scoped::All(&state.internal), + Contents::All( + state + .panes + .iter() + .map(|(pane, pane_state)| { + (*pane, view(*pane, pane_state, false)) + }) + .collect(), + &state.internal, ) }; Self { contents, - state, width: Length::Fill, height: Length::Fill, spacing: 0, @@ -254,12 +251,12 @@ where fn diff(&self, tree: &mut Tree) { match &self.contents { - Contents::All(contents) => tree.diff_children_custom( + Contents::All(contents, _) => tree.diff_children_custom( contents, |state, (_, content)| content.diff(state), |(_, content)| content.state(), ), - Contents::Maximized(_, content) => tree.diff_children_custom( + Contents::Maximized(_, content, _) => tree.diff_children_custom( &[content], |state, content| content.diff(state), |content| content.state(), @@ -283,7 +280,7 @@ where layout( renderer, limits, - &self.state, + self.contents.layout(), self.width, self.height, self.spacing, @@ -312,7 +309,7 @@ where let event_status = update( action, - &self.state, + self.contents.layout(), &event, layout, cursor_position, @@ -357,7 +354,7 @@ where ) -> mouse::Interaction { mouse_interaction( tree.state.downcast_ref(), - &self.state, + self.contents.layout(), layout, cursor_position, self.spacing, @@ -395,7 +392,7 @@ where ) { draw( tree.state.downcast_ref(), - &self.state, + self.contents.layout(), layout, cursor_position, renderer, @@ -460,10 +457,10 @@ where } /// Calculates the [`Layout`] of a [`PaneGrid`]. -pub fn layout<'a, Renderer, T>( +pub fn layout( renderer: &Renderer, limits: &layout::Limits, - state: &state::Scoped<'a>, + node: &Node, width: Length, height: Length, spacing: u16, @@ -473,7 +470,7 @@ pub fn layout<'a, Renderer, T>( let limits = limits.width(width).height(height); let size = limits.resolve(Size::ZERO); - let regions = state.layout().pane_regions(f32::from(spacing), size); + let regions = node.pane_regions(f32::from(spacing), size); let children = contents .filter_map(|(pane, content)| { let region = regions.get(&pane)?; @@ -498,7 +495,7 @@ pub fn layout<'a, Renderer, T>( /// accordingly. pub fn update<'a, Message, T: Draggable>( action: &mut state::Action, - state: &state::Scoped<'a>, + node: &Node, event: &Event, layout: Layout<'_>, cursor_position: Point, @@ -526,7 +523,7 @@ pub fn update<'a, Message, T: Draggable>( cursor_position.y - bounds.y, ); - let splits = state.layout().split_regions( + let splits = node.split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -604,7 +601,7 @@ pub fn update<'a, Message, T: Draggable>( if let Some((split, _)) = action.picked_split() { let bounds = layout.bounds(); - let splits = state.layout().split_regions( + let splits = node.split_regions( f32::from(spacing), Size::new(bounds.width, bounds.height), ); @@ -674,9 +671,9 @@ fn click_pane<'a, Message, T>( } /// Returns the current [`mouse::Interaction`] of a [`PaneGrid`]. -pub fn mouse_interaction<'a>( +pub fn mouse_interaction( action: &state::Action, - state: &state::Scoped<'a>, + node: &Node, layout: Layout<'_>, cursor_position: Point, spacing: u16, @@ -691,9 +688,8 @@ pub fn mouse_interaction<'a>( resize_leeway.and_then(|leeway| { let bounds = layout.bounds(); - let splits = state - .layout() - .split_regions(f32::from(spacing), bounds.size()); + let splits = + node.split_regions(f32::from(spacing), bounds.size()); let relative_cursor = Point::new( cursor_position.x - bounds.x, @@ -720,9 +716,9 @@ pub fn mouse_interaction<'a>( } /// Draws a [`PaneGrid`]. -pub fn draw<'a, Renderer, T>( +pub fn draw( action: &state::Action, - state: &state::Scoped<'a>, + node: &Node, layout: Layout<'_>, cursor_position: Point, renderer: &mut Renderer, @@ -752,9 +748,7 @@ pub fn draw<'a, Renderer, T>( .and_then(|(split, axis)| { let bounds = layout.bounds(); - let splits = state - .layout() - .split_regions(f32::from(spacing), bounds.size()); + let splits = node.split_regions(f32::from(spacing), bounds.size()); let (_axis, region, ratio) = splits.get(&split)?; @@ -772,9 +766,8 @@ pub fn draw<'a, Renderer, T>( cursor_position.y - bounds.y, ); - let splits = state - .layout() - .split_regions(f32::from(spacing), bounds.size()); + let splits = + node.split_regions(f32::from(spacing), bounds.size()); let (_split, axis, region) = hovered_split( splits.iter(), @@ -938,21 +931,29 @@ fn hovered_split<'a>( /// The visible contents of the [`PaneGrid`] #[derive(Debug)] -pub enum Contents { +pub enum Contents<'a, T> { /// All panes are visible - All(Vec<(Pane, T)>), + All(Vec<(Pane, T)>, &'a state::Internal), /// A maximized pane is visible - Maximized(Pane, T), + Maximized(Pane, T, Node), } -impl Contents { +impl<'a, T> Contents<'a, T> { + /// Returns the layout [`Node`] of the [`Contents`] + pub fn layout(&self) -> &Node { + match self { + Contents::All(_, state) => state.layout(), + Contents::Maximized(_, _, layout) => layout, + } + } + /// Returns an iterator over the values of the [`Contents`] pub fn iter(&self) -> Box + '_> { match self { - Contents::All(contents) => Box::new( + Contents::All(contents, _) => Box::new( contents.iter().map(|(pane, content)| (*pane, content)), ), - Contents::Maximized(pane, content) => { + Contents::Maximized(pane, content, _) => { Box::new(std::iter::once((*pane, content))) } } @@ -960,10 +961,10 @@ impl Contents { fn iter_mut(&mut self) -> Box + '_> { match self { - Contents::All(contents) => Box::new( + Contents::All(contents, _) => Box::new( contents.iter_mut().map(|(pane, content)| (*pane, content)), ), - Contents::Maximized(pane, content) => { + Contents::Maximized(pane, content, _) => { Box::new(std::iter::once((*pane, content))) } } diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index c9e9433d..58397444 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -293,17 +293,6 @@ impl Internal { } } -/// The scoped internal state of the [`PaneGrid`] -/// -/// [`PaneGrid`]: crate::widget::PaneGrid -#[derive(Debug)] -pub enum Scoped<'a> { - /// The state when all panes are visible - All(&'a Internal), - /// The state when a pane is maximized - Maximized(Node), -} - /// The current action of a [`PaneGrid`]. /// /// [`PaneGrid`]: crate::widget::PaneGrid @@ -351,12 +340,9 @@ impl Action { } } -impl<'a> Scoped<'a> { - /// The layout [`Node`] of the [`Scoped`] state +impl Internal { + /// The layout [`Node`] of the [`Internal`] state pub fn layout(&self) -> &Node { - match self { - Scoped::All(Internal { layout, .. }) => layout, - Scoped::Maximized(layout) => layout, - } + &self.layout } } -- cgit From 18fb74f20092b2703a90afdb01f39754445998da Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 9 Nov 2022 04:05:31 +0100 Subject: Introduce `Custom` variants for every style in the built-in `Theme` --- native/src/overlay/menu.rs | 6 +++--- native/src/widget/button.rs | 4 ++-- native/src/widget/checkbox.rs | 4 ++-- native/src/widget/container.rs | 2 +- native/src/widget/helpers.rs | 9 +++++++- native/src/widget/pane_grid.rs | 4 ++-- native/src/widget/pane_grid/content.rs | 2 +- native/src/widget/pane_grid/title_bar.rs | 2 +- native/src/widget/pick_list.rs | 36 +++++++++++++++++++++++++------- native/src/widget/progress_bar.rs | 2 +- native/src/widget/radio.rs | 4 ++-- native/src/widget/rule.rs | 2 +- native/src/widget/scrollable.rs | 4 ++-- native/src/widget/slider.rs | 10 ++++----- native/src/widget/text_input.rs | 6 +++--- native/src/widget/toggler.rs | 4 ++-- native/src/widget/tooltip.rs | 4 ++-- 17 files changed, 67 insertions(+), 38 deletions(-) (limited to 'native') diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index 08135872..3b55eba1 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -178,7 +178,7 @@ where font, text_size, padding, - style, + style: style.clone(), })); state.tree.diff(&container as &dyn Widget<_, _>); @@ -288,7 +288,7 @@ where layout: Layout<'_>, cursor_position: Point, ) { - let appearance = theme.appearance(self.style); + let appearance = theme.appearance(&self.style); let bounds = layout.bounds(); renderer.fill_quad( @@ -460,7 +460,7 @@ where _cursor_position: Point, viewport: &Rectangle, ) { - let appearance = theme.appearance(self.style); + let appearance = theme.appearance(&self.style); let bounds = layout.bounds(); let text_size = diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 1582188b..fa5da24b 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -231,7 +231,7 @@ where cursor_position, self.on_press.is_some(), theme, - self.style, + &self.style, || tree.state.downcast_ref::(), ); @@ -361,7 +361,7 @@ pub fn draw<'a, Renderer: crate::Renderer>( style_sheet: &dyn StyleSheet< Style = ::Style, >, - style: ::Style, + style: &::Style, state: impl FnOnce() -> &'a State, ) -> Appearance where diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index dc3c0bd0..77d639a9 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -224,9 +224,9 @@ where let mut children = layout.children(); let custom_style = if is_mouse_over { - theme.hovered(self.style, self.is_checked) + theme.hovered(&self.style, self.is_checked) } else { - theme.active(self.style, self.is_checked) + theme.active(&self.style, self.is_checked) }; { diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 10a80b58..16537c50 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -228,7 +228,7 @@ where cursor_position: Point, viewport: &Rectangle, ) { - let style = theme.appearance(self.style); + let style = theme.appearance(&self.style); draw_background(renderer, &style, layout.bounds()); diff --git a/native/src/widget/helpers.rs b/native/src/widget/helpers.rs index 79751878..fe6fb815 100644 --- a/native/src/widget/helpers.rs +++ b/native/src/widget/helpers.rs @@ -1,4 +1,5 @@ //! Helper functions to create pure widgets. +use crate::overlay; use crate::widget; use crate::{Element, Length}; @@ -84,6 +85,7 @@ pub fn button<'a, Message, Renderer>( where Renderer: crate::Renderer, Renderer::Theme: widget::button::StyleSheet, + ::Style: Default, { widget::Button::new(content) } @@ -208,7 +210,12 @@ where T: ToString + Eq + 'static, [T]: ToOwned>, Renderer: crate::text::Renderer, - Renderer::Theme: widget::pick_list::StyleSheet, + Renderer::Theme: widget::pick_list::StyleSheet + + widget::scrollable::StyleSheet + + overlay::menu::StyleSheet + + widget::container::StyleSheet, + ::Style: + From<::Style>, { widget::PickList::new(options, selected, on_selected) } diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index fd771f8b..ff902aa7 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -401,7 +401,7 @@ where viewport, self.spacing, self.on_resize.as_ref().map(|(leeway, _)| *leeway), - self.style, + &self.style, self.contents .iter() .zip(&tree.children) @@ -727,7 +727,7 @@ pub fn draw( viewport: &Rectangle, spacing: u16, resize_leeway: Option, - style: ::Style, + style: &::Style, contents: impl Iterator, draw_pane: impl Fn( T, diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index c236d820..405dc0b2 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -103,7 +103,7 @@ where let bounds = layout.bounds(); { - let style = theme.appearance(self.style); + let style = theme.appearance(&self.style); container::draw_background(renderer, &style, bounds); } diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index eb85f924..783a14c3 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -129,7 +129,7 @@ where use container::StyleSheet; let bounds = layout.bounds(); - let style = theme.appearance(self.style); + let style = theme.appearance(&self.style); let inherited_style = renderer::Style { text_color: style.text_color.unwrap_or(inherited_style.text_color), }; diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 896f5b35..a6459cd6 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -9,6 +9,8 @@ use crate::overlay::menu::{self, Menu}; use crate::renderer; use crate::text::{self, Text}; use crate::touch; +use crate::widget::container; +use crate::widget::scrollable; use crate::widget::tree::{self, Tree}; use crate::{ Clipboard, Element, Layout, Length, Padding, Point, Rectangle, Shell, Size, @@ -42,7 +44,12 @@ where T: ToString + Eq, [T]: ToOwned>, Renderer: text::Renderer, - Renderer::Theme: StyleSheet, + Renderer::Theme: StyleSheet + + scrollable::StyleSheet + + menu::StyleSheet + + container::StyleSheet, + ::Style: + From<::Style>, { /// The default padding of a [`PickList`]. pub const DEFAULT_PADDING: Padding = Padding::new(5); @@ -114,7 +121,12 @@ where [T]: ToOwned>, Message: 'a, Renderer: text::Renderer + 'a, - Renderer::Theme: StyleSheet, + Renderer::Theme: StyleSheet + + scrollable::StyleSheet + + menu::StyleSheet + + container::StyleSheet, + ::Style: + From<::Style>, { fn tag(&self) -> tree::Tag { tree::Tag::of::>() @@ -202,7 +214,7 @@ where &self.font, self.placeholder.as_deref(), self.selected.as_ref(), - self.style, + &self.style, ) } @@ -221,7 +233,7 @@ where self.text_size, self.font.clone(), &self.options, - self.style, + self.style.clone(), ) } } @@ -233,7 +245,12 @@ where [T]: ToOwned>, Message: 'a, Renderer: text::Renderer + 'a, - Renderer::Theme: StyleSheet, + Renderer::Theme: StyleSheet + + scrollable::StyleSheet + + menu::StyleSheet + + container::StyleSheet, + ::Style: + From<::Style>, { fn from(pick_list: PickList<'a, T, Message, Renderer>) -> Self { Self::new(pick_list) @@ -456,7 +473,12 @@ where T: Clone + ToString, Message: 'a, Renderer: text::Renderer + 'a, - Renderer::Theme: StyleSheet, + Renderer::Theme: StyleSheet + + scrollable::StyleSheet + + menu::StyleSheet + + container::StyleSheet, + ::Style: + From<::Style>, { if state.is_open { let bounds = layout.bounds(); @@ -493,7 +515,7 @@ pub fn draw( font: &Renderer::Font, placeholder: Option<&str>, selected: Option<&T>, - style: ::Style, + style: &::Style, ) where Renderer: text::Renderer, Renderer::Theme: StyleSheet, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 8a945433..b053d959 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -124,7 +124,7 @@ where / (range_end - range_start) }; - let style = theme.appearance(self.style); + let style = theme.appearance(&self.style); renderer.fill_quad( renderer::Quad { diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index cb83f745..743689c7 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -230,9 +230,9 @@ where let mut children = layout.children(); let custom_style = if is_mouse_over { - theme.hovered(self.style, self.is_selected) + theme.hovered(&self.style, self.is_selected) } else { - theme.active(self.style, self.is_selected) + theme.active(&self.style, self.is_selected) }; { diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 56f8c80d..e44d8d99 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -88,7 +88,7 @@ where _viewport: &Rectangle, ) { let bounds = layout.bounds(); - let style = theme.style(self.style); + let style = theme.appearance(&self.style); let bounds = if self.is_horizontal { let line_y = (bounds.y + (bounds.height / 2.0) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 4ebb07a0..b257cbe5 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -233,7 +233,7 @@ where self.scrollbar_width, self.scrollbar_margin, self.scroller_width, - self.style, + &self.style, |renderer, layout, cursor_position, viewport| { self.content.as_widget().draw( &tree.children[0], @@ -627,7 +627,7 @@ pub fn draw( scrollbar_width: u16, scrollbar_margin: u16, scroller_width: u16, - style: ::Style, + style: &::Style, draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle), ) where Renderer: crate::Renderer, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 585d9c35..92ed72e9 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -222,7 +222,7 @@ where self.value, &self.range, theme, - self.style, + &self.style, ) } @@ -353,7 +353,7 @@ pub fn draw( value: T, range: &RangeInclusive, style_sheet: &dyn StyleSheet