diff options
Diffstat (limited to 'widget')
-rw-r--r-- | widget/src/canvas.rs | 30 | ||||
-rw-r--r-- | widget/src/canvas/program.rs | 5 | ||||
-rw-r--r-- | widget/src/image.rs | 10 | ||||
-rw-r--r-- | widget/src/image/viewer.rs | 7 | ||||
-rw-r--r-- | widget/src/lazy/component.rs | 2 | ||||
-rw-r--r-- | widget/src/lazy/responsive.rs | 45 | ||||
-rw-r--r-- | widget/src/qr_code.rs | 9 | ||||
-rw-r--r-- | widget/src/svg.rs | 6 |
8 files changed, 81 insertions, 33 deletions
diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs index 0eda0191..7a21895a 100644 --- a/widget/src/canvas.rs +++ b/widget/src/canvas.rs @@ -6,8 +6,10 @@ mod program; pub use event::Event; pub use program::Program; -pub use crate::graphics::geometry::*; -pub use crate::renderer::geometry::*; +pub use crate::graphics::geometry::{ + fill, gradient, path, stroke, Fill, Gradient, LineCap, LineDash, LineJoin, + Path, Stroke, Style, Text, +}; use crate::core; use crate::core::layout::{self, Layout}; @@ -21,6 +23,19 @@ use crate::graphics::geometry; use std::marker::PhantomData; +/// A simple cache that stores generated [`Geometry`] to avoid recomputation. +/// +/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer +/// change or it is explicitly cleared. +pub type Cache<Renderer = crate::Renderer> = geometry::Cache<Renderer>; + +/// The geometry supported by a renderer. +pub type Geometry<Renderer = crate::Renderer> = + <Renderer as geometry::Renderer>::Geometry; + +/// The frame supported by a renderer. +pub type Frame<Renderer = crate::Renderer> = geometry::Frame<Renderer>; + /// A widget capable of drawing 2D graphics. /// /// ## Drawing a simple circle @@ -42,7 +57,7 @@ use std::marker::PhantomData; /// impl Program<()> for Circle { /// type State = (); /// -/// fn draw(&self, _state: &(), renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor) -> Vec<Geometry>{ +/// fn draw(&self, _state: &(), renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor) -> Vec<Geometry> { /// // We prepare a new `Frame` /// let mut frame = Frame::new(renderer, bounds.size()); /// @@ -210,9 +225,12 @@ where renderer.with_transformation( Transformation::translate(bounds.x, bounds.y), |renderer| { - renderer.draw( - self.program.draw(state, renderer, theme, bounds, cursor), - ); + let layers = + self.program.draw(state, renderer, theme, bounds, cursor); + + for layer in layers { + renderer.draw_geometry(layer); + } }, ); } diff --git a/widget/src/canvas/program.rs b/widget/src/canvas/program.rs index 0bff4bda..a7ded0f4 100644 --- a/widget/src/canvas/program.rs +++ b/widget/src/canvas/program.rs @@ -1,5 +1,6 @@ use crate::canvas::event::{self, Event}; use crate::canvas::mouse; +use crate::canvas::Geometry; use crate::core::Rectangle; use crate::graphics::geometry; @@ -52,7 +53,7 @@ where theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) -> Vec<Renderer::Geometry>; + ) -> Vec<Geometry<Renderer>>; /// Returns the current mouse interaction of the [`Program`]. /// @@ -94,7 +95,7 @@ where theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) -> Vec<Renderer::Geometry> { + ) -> Vec<Geometry<Renderer>> { T::draw(self, state, renderer, theme, bounds, cursor) } diff --git a/widget/src/image.rs b/widget/src/image.rs index ccf1f175..f673c7b3 100644 --- a/widget/src/image.rs +++ b/widget/src/image.rs @@ -93,7 +93,7 @@ where { // The raw w/h of the underlying image let image_size = { - let Size { width, height } = renderer.dimensions(handle); + let Size { width, height } = renderer.measure_image(handle); Size::new(width as f32, height as f32) }; @@ -130,7 +130,7 @@ pub fn draw<Renderer, Handle>( Renderer: image::Renderer<Handle = Handle>, Handle: Clone + Hash, { - let Size { width, height } = renderer.dimensions(handle); + let Size { width, height } = renderer.measure_image(handle); let image_size = Size::new(width as f32, height as f32); let bounds = layout.bounds(); @@ -148,7 +148,11 @@ pub fn draw<Renderer, Handle>( ..bounds }; - renderer.draw(handle.clone(), filter_method, drawing_bounds + offset); + renderer.draw_image( + handle.clone(), + filter_method, + drawing_bounds + offset, + ); }; if adjusted_fit.width > bounds.width || adjusted_fit.height > bounds.height diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs index 2e3fd713..5f7bb345 100644 --- a/widget/src/image/viewer.rs +++ b/widget/src/image/viewer.rs @@ -117,7 +117,7 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let Size { width, height } = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.measure_image(&self.handle); let mut size = limits.resolve( self.width, @@ -335,8 +335,7 @@ where renderer.with_layer(bounds, |renderer| { renderer.with_translation(translation, |renderer| { - image::Renderer::draw( - renderer, + renderer.draw_image( self.handle.clone(), self.filter_method, Rectangle { @@ -421,7 +420,7 @@ pub fn image_size<Renderer>( where Renderer: image::Renderer, { - let Size { width, height } = renderer.dimensions(handle); + let Size { width, height } = renderer.measure_image(handle); let (width, height) = { let dimensions = (width as f32, height as f32); diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs index a512e0de..7ba71a02 100644 --- a/widget/src/lazy/component.rs +++ b/widget/src/lazy/component.rs @@ -478,12 +478,14 @@ where translation: Vector, ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { self.rebuild_element_if_necessary(); + let tree = tree .state .downcast_mut::<Rc<RefCell<Option<Tree>>>>() .borrow_mut() .take() .unwrap(); + let overlay = Overlay(Some( InnerBuilder { instance: self, diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs index 313e1edb..f612102e 100644 --- a/widget/src/lazy/responsive.rs +++ b/widget/src/lazy/responsive.rs @@ -308,10 +308,13 @@ where content_layout_node.as_ref().unwrap(), ); - element - .as_widget_mut() - .overlay(tree, content_layout, renderer, translation) - .map(|overlay| RefCell::new(Nested::new(overlay))) + ( + element + .as_widget_mut() + .overlay(tree, content_layout, renderer, translation) + .map(|overlay| RefCell::new(Nested::new(overlay))), + content_layout_node, + ) }, } .build(); @@ -341,7 +344,10 @@ struct Overlay<'a, 'b, Message, Theme, Renderer> { #[borrows(mut content, mut tree)] #[not_covariant] - overlay: Option<RefCell<Nested<'this, Message, Theme, Renderer>>>, + overlay: ( + Option<RefCell<Nested<'this, Message, Theme, Renderer>>>, + &'this mut Option<layout::Node>, + ), } impl<'a, 'b, Message, Theme, Renderer> @@ -351,7 +357,7 @@ impl<'a, 'b, Message, Theme, Renderer> &self, f: impl FnOnce(&mut Nested<'_, Message, Theme, Renderer>) -> T, ) -> Option<T> { - self.with_overlay(|overlay| { + self.with_overlay(|(overlay, _layout)| { overlay.as_ref().map(|nested| (f)(&mut nested.borrow_mut())) }) } @@ -360,7 +366,7 @@ impl<'a, 'b, Message, Theme, Renderer> &mut self, f: impl FnOnce(&mut Nested<'_, Message, Theme, Renderer>) -> T, ) -> Option<T> { - self.with_overlay_mut(|overlay| { + self.with_overlay_mut(|(overlay, _layout)| { overlay.as_mut().map(|nested| (f)(nested.get_mut())) }) } @@ -412,10 +418,27 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - self.with_overlay_mut_maybe(|overlay| { - overlay.on_event(event, layout, cursor, renderer, clipboard, shell) - }) - .unwrap_or(event::Status::Ignored) + let mut is_layout_invalid = false; + + let event_status = self + .with_overlay_mut_maybe(|overlay| { + let event_status = overlay.on_event( + event, layout, cursor, renderer, clipboard, shell, + ); + + is_layout_invalid = shell.is_layout_invalid(); + + event_status + }) + .unwrap_or(event::Status::Ignored); + + if is_layout_invalid { + self.with_overlay_mut(|(_overlay, layout)| { + **layout = None; + }); + } + + event_status } fn is_over( diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs index 3cc2c294..300028b9 100644 --- a/widget/src/qr_code.rs +++ b/widget/src/qr_code.rs @@ -8,7 +8,6 @@ use crate::core::{ Color, Element, Layout, Length, Point, Rectangle, Size, Theme, Vector, Widget, }; -use crate::graphics::geometry::Renderer as _; use crate::Renderer; use std::cell::RefCell; @@ -158,7 +157,9 @@ where renderer.with_translation( bounds.position() - Point::ORIGIN, |renderer| { - renderer.draw(vec![geometry]); + use crate::graphics::geometry::Renderer as _; + + renderer.draw_geometry(geometry); }, ); } @@ -177,11 +178,11 @@ where /// The data of a [`QRCode`]. /// /// It stores the contents that will be displayed. -#[derive(Debug)] +#[allow(missing_debug_implementations)] pub struct Data { contents: Vec<qrcode::Color>, width: usize, - cache: canvas::Cache, + cache: canvas::Cache<Renderer>, } impl Data { diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 66988097..eb142189 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -117,7 +117,7 @@ where limits: &layout::Limits, ) -> layout::Node { // The raw w/h of the underlying image - let Size { width, height } = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.measure_svg(&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 @@ -151,7 +151,7 @@ where cursor: mouse::Cursor, _viewport: &Rectangle, ) { - let Size { width, height } = renderer.dimensions(&self.handle); + let Size { width, height } = renderer.measure_svg(&self.handle); let image_size = Size::new(width as f32, height as f32); let bounds = layout.bounds(); @@ -178,7 +178,7 @@ where let style = theme.style(&self.class, status); - renderer.draw( + renderer.draw_svg( self.handle.clone(), style.color, drawing_bounds + offset, |