From 4bd44e4ed218e01c4cd59c7fd37db28a0e02637a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 18 Aug 2020 03:37:32 +0200 Subject: [PATCH] Introduce `viewport` to `Widget::draw` This should eventually allow us to only generate primitives that are visible. --- examples/custom_widget/src/main.rs | 3 ++- examples/geometry/src/main.rs | 5 +++-- graphics/src/renderer.rs | 3 ++- graphics/src/widget/button.rs | 1 + graphics/src/widget/canvas.rs | 5 +++-- graphics/src/widget/column.rs | 12 +++++++++--- graphics/src/widget/container.rs | 10 ++++++++-- graphics/src/widget/pane_grid.rs | 3 ++- graphics/src/widget/row.rs | 12 +++++++++--- native/src/element.rs | 13 +++++++++---- native/src/layout/debugger.rs | 3 ++- native/src/overlay/menu.rs | 11 ++++++++--- native/src/renderer/null.rs | 3 +++ native/src/user_interface.rs | 8 +++++++- native/src/widget.rs | 5 ++++- native/src/widget/button.rs | 1 + native/src/widget/checkbox.rs | 1 + native/src/widget/column.rs | 16 +++++++++++++--- native/src/widget/container.rs | 3 +++ native/src/widget/image.rs | 4 +++- native/src/widget/pane_grid.rs | 1 + native/src/widget/pick_list.rs | 1 + native/src/widget/progress_bar.rs | 1 + native/src/widget/radio.rs | 1 + native/src/widget/row.rs | 19 ++++++++++++++----- native/src/widget/scrollable.rs | 5 +++++ native/src/widget/slider.rs | 1 + native/src/widget/space.rs | 1 + native/src/widget/svg.rs | 4 +++- native/src/widget/text.rs | 1 + native/src/widget/text_input.rs | 1 + 31 files changed, 123 insertions(+), 35 deletions(-) diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index bcf896b0..adb45ef9 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -12,7 +12,7 @@ mod circle { use iced_graphics::{Backend, Defaults, Primitive, Renderer}; use iced_native::{ layout, mouse, Background, Color, Element, Hasher, Layout, Length, - Point, Size, Widget, + Point, Rectangle, Size, Widget, }; pub struct Circle { @@ -60,6 +60,7 @@ mod circle { _defaults: &Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> (Primitive, mouse::Interaction) { ( Primitive::Quad { diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 71ce0d8c..be5277a9 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -15,8 +15,8 @@ mod rainbow { Backend, Defaults, Primitive, Renderer, }; use iced_native::{ - layout, mouse, Element, Hasher, Layout, Length, Point, Size, Vector, - Widget, + layout, mouse, Element, Hasher, Layout, Length, Point, Rectangle, Size, + Vector, Widget, }; pub struct Rainbow; @@ -57,6 +57,7 @@ mod rainbow { _defaults: &Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> (Primitive, mouse::Interaction) { let b = layout.bounds(); diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 5d51e6d4..a880e22a 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -96,10 +96,11 @@ where widget: &dyn Widget, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, color: Color, ) -> Self::Output { let (primitive, cursor) = - widget.draw(self, defaults, layout, cursor_position); + widget.draw(self, defaults, layout, cursor_position, viewport); let mut primitives = Vec::new(); diff --git a/graphics/src/widget/button.rs b/graphics/src/widget/button.rs index ecabc868..a1afc940 100644 --- a/graphics/src/widget/button.rs +++ b/graphics/src/widget/button.rs @@ -62,6 +62,7 @@ where }, content_layout, cursor_position, + &bounds, ); ( diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs index bc0802e5..73778d16 100644 --- a/graphics/src/widget/canvas.rs +++ b/graphics/src/widget/canvas.rs @@ -8,8 +8,8 @@ //! [`Frame`]: struct.Frame.html use crate::{Backend, Defaults, Primitive, Renderer}; use iced_native::{ - layout, mouse, Clipboard, Element, Hasher, Layout, Length, Point, Size, - Vector, Widget, + layout, mouse, Clipboard, Element, Hasher, Layout, Length, Point, + Rectangle, Size, Vector, Widget, }; use std::hash::Hash; use std::marker::PhantomData; @@ -196,6 +196,7 @@ where _defaults: &Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> (Primitive, mouse::Interaction) { let bounds = layout.bounds(); let translation = Vector::new(bounds.x, bounds.y); diff --git a/graphics/src/widget/column.rs b/graphics/src/widget/column.rs index 6c7235c7..0cf56842 100644 --- a/graphics/src/widget/column.rs +++ b/graphics/src/widget/column.rs @@ -1,7 +1,7 @@ use crate::{Backend, Primitive, Renderer}; use iced_native::column; use iced_native::mouse; -use iced_native::{Element, Layout, Point}; +use iced_native::{Element, Layout, Point, Rectangle}; /// A container that distributes its contents vertically. pub type Column<'a, Message, Backend> = @@ -17,6 +17,7 @@ where content: &[Element<'_, Message, Self>], layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Self::Output { let mut mouse_interaction = mouse::Interaction::default(); @@ -26,8 +27,13 @@ where .iter() .zip(layout.children()) .map(|(child, layout)| { - let (primitive, new_mouse_interaction) = - child.draw(self, defaults, layout, cursor_position); + let (primitive, new_mouse_interaction) = child.draw( + self, + defaults, + layout, + cursor_position, + viewport, + ); if new_mouse_interaction > mouse_interaction { mouse_interaction = new_mouse_interaction; diff --git a/graphics/src/widget/container.rs b/graphics/src/widget/container.rs index 5b3a01d2..4854f589 100644 --- a/graphics/src/widget/container.rs +++ b/graphics/src/widget/container.rs @@ -24,6 +24,7 @@ where defaults: &Defaults, bounds: Rectangle, cursor_position: Point, + viewport: &Rectangle, style_sheet: &Self::Style, content: &Element<'_, Message, Self>, content_layout: Layout<'_>, @@ -36,8 +37,13 @@ where }, }; - let (content, mouse_interaction) = - content.draw(self, &defaults, content_layout, cursor_position); + let (content, mouse_interaction) = content.draw( + self, + &defaults, + content_layout, + cursor_position, + viewport, + ); if let Some(background) = background(bounds, &style) { ( diff --git a/graphics/src/widget/pane_grid.rs b/graphics/src/widget/pane_grid.rs index aa8a3f7c..5b0eb391 100644 --- a/graphics/src/widget/pane_grid.rs +++ b/graphics/src/widget/pane_grid.rs @@ -137,7 +137,7 @@ where let (body, body_layout) = body; let (body_primitive, body_interaction) = - body.draw(self, defaults, body_layout, cursor_position); + body.draw(self, defaults, body_layout, cursor_position, &bounds); let background = crate::widget::container::background(bounds, &style); @@ -224,6 +224,7 @@ where &defaults, controls_layout, cursor_position, + &bounds, ); ( diff --git a/graphics/src/widget/row.rs b/graphics/src/widget/row.rs index 4c1dbadc..397d80bf 100644 --- a/graphics/src/widget/row.rs +++ b/graphics/src/widget/row.rs @@ -1,7 +1,7 @@ use crate::{Backend, Primitive, Renderer}; use iced_native::mouse; use iced_native::row; -use iced_native::{Element, Layout, Point}; +use iced_native::{Element, Layout, Point, Rectangle}; /// A container that distributes its contents horizontally. pub type Row<'a, Message, Backend> = @@ -17,6 +17,7 @@ where content: &[Element<'_, Message, Self>], layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Self::Output { let mut mouse_interaction = mouse::Interaction::default(); @@ -26,8 +27,13 @@ where .iter() .zip(layout.children()) .map(|(child, layout)| { - let (primitive, new_mouse_interaction) = - child.draw(self, defaults, layout, cursor_position); + let (primitive, new_mouse_interaction) = child.draw( + self, + defaults, + layout, + cursor_position, + viewport, + ); if new_mouse_interaction > mouse_interaction { mouse_interaction = new_mouse_interaction; diff --git a/native/src/element.rs b/native/src/element.rs index 514a135b..10e1b5fb 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -1,6 +1,7 @@ +use crate::layout; +use crate::overlay; use crate::{ - layout, overlay, Clipboard, Color, Event, Hasher, Layout, Length, Point, - Widget, + Clipboard, Color, Event, Hasher, Layout, Length, Point, Rectangle, Widget, }; /// A generic [`Widget`]. @@ -260,9 +261,10 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { self.widget - .draw(renderer, defaults, layout, cursor_position) + .draw(renderer, defaults, layout, cursor_position, viewport) } /// Computes the _layout_ hash of the [`Element`]. @@ -356,9 +358,10 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { self.widget - .draw(renderer, defaults, layout, cursor_position) + .draw(renderer, defaults, layout, cursor_position, viewport) } fn hash_layout(&self, state: &mut Hasher) { @@ -437,12 +440,14 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { renderer.explain( defaults, self.element.widget.as_ref(), layout, cursor_position, + viewport, self.color, ) } diff --git a/native/src/layout/debugger.rs b/native/src/layout/debugger.rs index e4b21609..4c6dd793 100644 --- a/native/src/layout/debugger.rs +++ b/native/src/layout/debugger.rs @@ -1,4 +1,4 @@ -use crate::{Color, Layout, Point, Renderer, Widget}; +use crate::{Color, Layout, Point, Rectangle, Renderer, Widget}; /// A renderer able to graphically explain a [`Layout`]. /// @@ -21,6 +21,7 @@ pub trait Debugger: Renderer { widget: &dyn Widget, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, color: Color, ) -> Self::Output; } diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index c2df468e..29e4e63d 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -253,9 +253,13 @@ where layout: Layout<'_>, cursor_position: Point, ) -> Renderer::Output { - let primitives = - self.container - .draw(renderer, defaults, layout, cursor_position); + let primitives = self.container.draw( + renderer, + defaults, + layout, + cursor_position, + &layout.bounds(), + ); renderer.decorate( layout.bounds(), @@ -368,6 +372,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { self::Renderer::draw( renderer, diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 2aee0da1..2f68498f 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -35,6 +35,7 @@ impl column::Renderer for Null { _content: &[Element<'_, Message, Self>], _layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) { } } @@ -46,6 +47,7 @@ impl row::Renderer for Null { _content: &[Element<'_, Message, Self>], _layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) { } } @@ -234,6 +236,7 @@ impl container::Renderer for Null { _defaults: &Self::Defaults, _bounds: Rectangle, _cursor_position: Point, + _viewport: &Rectangle, _style: &Self::Style, _content: &Element<'_, Message, Self>, _content_layout: Layout<'_>, diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 00a290f1..59d91f42 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -1,4 +1,6 @@ -use crate::{layout, overlay, Clipboard, Element, Event, Layout, Point, Size}; +use crate::layout; +use crate::overlay; +use crate::{Clipboard, Element, Event, Layout, Point, Rectangle, Size}; use std::hash::Hasher; @@ -327,6 +329,8 @@ where renderer: &mut Renderer, cursor_position: Point, ) -> Renderer::Output { + let viewport = Rectangle::with_size(self.bounds); + let overlay = if let Some(mut overlay) = self.root.overlay(Layout::new(&self.base.layout)) { @@ -365,6 +369,7 @@ where &Renderer::Defaults::default(), Layout::new(&self.base.layout), base_cursor, + &viewport, ); renderer.overlay( @@ -378,6 +383,7 @@ where &Renderer::Defaults::default(), Layout::new(&self.base.layout), cursor_position, + &viewport, ) } } diff --git a/native/src/widget.rs b/native/src/widget.rs index 8539e519..39fabce1 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -70,7 +70,9 @@ pub use text::Text; #[doc(no_inline)] pub use text_input::TextInput; -use crate::{layout, overlay, Clipboard, Event, Hasher, Layout, Length, Point}; +use crate::{ + layout, overlay, Clipboard, Event, Hasher, Layout, Length, Point, Rectangle, +}; /// A component that displays information and allows interaction. /// @@ -134,6 +136,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output; /// Computes the _layout_ hash of the [`Widget`]. diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index c932da2b..37a03792 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -215,6 +215,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw( defaults, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 99178aae..e389427e 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -180,6 +180,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let bounds = layout.bounds(); let mut children = layout.children(); diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 42cfe9b9..6c4f6325 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -1,9 +1,11 @@ //! Distribute content vertically. use std::hash::Hash; +use crate::layout; +use crate::overlay; use crate::{ - layout, overlay, Align, Clipboard, Element, Event, Hasher, Layout, Length, - Point, Widget, + Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, Rectangle, + Widget, }; use std::u32; @@ -185,8 +187,15 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { - renderer.draw(defaults, &self.children, layout, cursor_position) + renderer.draw( + defaults, + &self.children, + layout, + cursor_position, + viewport, + ) } fn hash_layout(&self, state: &mut Hasher) { @@ -240,6 +249,7 @@ pub trait Renderer: crate::Renderer + Sized { content: &[Element<'_, Message, Self>], layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Self::Output; } diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index b8316e62..5b04d699 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -191,11 +191,13 @@ where defaults: &Renderer::Defaults, 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(), @@ -242,6 +244,7 @@ pub trait Renderer: crate::Renderer { defaults: &Self::Defaults, bounds: Rectangle, cursor_position: Point, + viewport: &Rectangle, style: &Self::Style, content: &Element<'_, Message, Self>, content_layout: Layout<'_>, diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 132f249d..9586da0f 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -1,5 +1,6 @@ //! Display images in your user interface. -use crate::{layout, Element, Hasher, Layout, Length, Point, Size, Widget}; +use crate::layout; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::{ hash::{Hash, Hasher as _}, @@ -97,6 +98,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw(self.handle.clone(), layout) } diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 5180fd3b..276bfae3 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -588,6 +588,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let picked_split = self .state diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 04478225..40a3cb7c 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -256,6 +256,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { self::Renderer::draw( renderer, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 5ab76d47..4f8a7e1b 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -104,6 +104,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw( layout.bounds(), diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 5b8d00e9..f5da6510 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -181,6 +181,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let bounds = layout.bounds(); let mut children = layout.children(); diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 2b6db224..6f50443d 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -1,11 +1,12 @@ //! Distribute content horizontally. -use std::hash::Hash; - +use crate::layout; +use crate::overlay; use crate::{ - layout, overlay, Align, Clipboard, Element, Event, Hasher, Layout, Length, - Point, Widget, + Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, Rectangle, + Widget, }; +use std::hash::Hash; use std::u32; /// A container that distributes its contents horizontally. @@ -186,8 +187,15 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { - renderer.draw(defaults, &self.children, layout, cursor_position) + renderer.draw( + defaults, + &self.children, + layout, + cursor_position, + viewport, + ) } fn hash_layout(&self, state: &mut Hasher) { @@ -242,6 +250,7 @@ pub trait Renderer: crate::Renderer + Sized { children: &[Element<'_, Message, Self>], layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Self::Output; } diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 75e97027..16950c5d 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -264,6 +264,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); @@ -289,6 +290,10 @@ where defaults, content_layout, cursor_position, + &Rectangle { + y: bounds.y + offset as f32, + ..bounds + }, ) }; diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index c49053f1..5e6fb8b4 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -257,6 +257,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let start = *self.range.start(); let end = *self.range.end(); diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index f1576ffb..032f341d 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -71,6 +71,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw(layout.bounds()) } diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 114d5e41..ede1aff8 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -1,5 +1,6 @@ //! Display vector graphics in your application. -use crate::{layout, Element, Hasher, Layout, Length, Point, Size, Widget}; +use crate::layout; +use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; use std::{ hash::{Hash, Hasher as _}, @@ -103,6 +104,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw(self.handle.clone(), layout) } diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 48a69e34..c2544b8e 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -149,6 +149,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, _cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { renderer.draw( defaults, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 9e15f4be..c3b9234a 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -493,6 +493,7 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let bounds = layout.bounds(); let text_bounds = layout.children().next().unwrap().bounds();