diff options
author | 2023-06-08 20:11:59 +0200 | |
---|---|---|
committer | 2023-06-08 20:11:59 +0200 | |
commit | 34451bff185d8875f55747ee97ed746828e30f40 (patch) | |
tree | 4cec93d3893aa6b744468af67e672383c6770afd | |
parent | c15f1b5f6575792cc89bb5fba2e613428397e46a (diff) | |
download | iced-34451bff185d8875f55747ee97ed746828e30f40.tar.gz iced-34451bff185d8875f55747ee97ed746828e30f40.tar.bz2 iced-34451bff185d8875f55747ee97ed746828e30f40.zip |
Implement basic cursor availability
55 files changed, 741 insertions, 896 deletions
diff --git a/core/src/element.rs b/core/src/element.rs index 98c53737..3268f14b 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -5,9 +5,7 @@ use crate::overlay; use crate::renderer; use crate::widget; use crate::widget::tree::{self, Tree}; -use crate::{ - Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Widget, -}; +use crate::{Clipboard, Color, Layout, Length, Rectangle, Shell, Widget}; use std::any::Any; use std::borrow::Borrow; @@ -378,7 +376,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, B>, @@ -390,7 +388,7 @@ where tree, event, layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -408,35 +406,23 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { - self.widget.draw( - tree, - renderer, - theme, - style, - layout, - cursor_position, - viewport, - ) + self.widget + .draw(tree, renderer, theme, style, layout, cursor, viewport) } fn mouse_interaction( &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - self.widget.mouse_interaction( - tree, - layout, - cursor_position, - viewport, - renderer, - ) + self.widget + .mouse_interaction(tree, layout, cursor, viewport, renderer) } fn overlay<'b>( @@ -521,20 +507,14 @@ where state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - self.element.widget.on_event( - state, - event, - layout, - cursor_position, - renderer, - clipboard, - shell, - ) + self.element + .widget + .on_event(state, event, layout, cursor, renderer, clipboard, shell) } fn draw( @@ -544,7 +524,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { fn explain_layout<Renderer: crate::Renderer>( @@ -567,15 +547,9 @@ where } } - self.element.widget.draw( - state, - renderer, - theme, - style, - layout, - cursor_position, - viewport, - ); + self.element + .widget + .draw(state, renderer, theme, style, layout, cursor, viewport); explain_layout(renderer, self.color, layout); } @@ -584,17 +558,13 @@ where &self, state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - self.element.widget.mouse_interaction( - state, - layout, - cursor_position, - viewport, - renderer, - ) + self.element + .widget + .mouse_interaction(state, layout, cursor, viewport, renderer) } fn overlay<'b>( diff --git a/core/src/mouse.rs b/core/src/mouse.rs index 0c405ce6..d13a60fb 100644 --- a/core/src/mouse.rs +++ b/core/src/mouse.rs @@ -2,10 +2,12 @@ pub mod click; mod button; +mod cursor; mod event; mod interaction; pub use button::Button; pub use click::Click; +pub use cursor::Cursor; pub use event::{Event, ScrollDelta}; pub use interaction::Interaction; diff --git a/core/src/mouse/cursor.rs b/core/src/mouse/cursor.rs new file mode 100644 index 00000000..d4cb415d --- /dev/null +++ b/core/src/mouse/cursor.rs @@ -0,0 +1,51 @@ +use crate::{Point, Rectangle, Vector}; + +/// The mouse cursor state. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Cursor { + /// The cursor has a defined position. + Available(Point), + + /// The cursor is currently unavailable (i.e. out of bounds or busy). + Unavailable, +} + +impl Cursor { + /// Returns the absolute position of the [`Cursor`], if available. + pub fn position(self) -> Option<Point> { + match self { + Cursor::Available(position) => Some(position), + Cursor::Unavailable => None, + } + } + + /// Returns the absolute position of the [`Cursor`], if available and inside + /// the given bounds. + /// + /// If the [`Cursor`] is not over the provided bounds, this method will + /// return `None`. + pub fn position_over(self, bounds: &Rectangle) -> Option<Point> { + self.position().filter(|p| bounds.contains(*p)) + } + + /// Returns the relative position of the [`Cursor`] inside the given bounds, + /// if available. + /// + /// If the [`Cursor`] is not over the provided bounds, this method will + /// return `None`. + pub fn position_in(self, bounds: &Rectangle) -> Option<Point> { + self.position_over(bounds) + .map(|p| p - Vector::new(bounds.x, bounds.y)) + } + + /// Returns the relative position of the [`Cursor`] from the given origin, + /// if available. + pub fn position_from(self, origin: Point) -> Option<Point> { + self.position().map(|p| p - Vector::new(origin.x, origin.y)) + } + + /// Returns true if the [`Cursor`] is over the given `bounds`. + pub fn is_over(self, bounds: &Rectangle) -> bool { + self.position_over(bounds).is_some() + } +} diff --git a/core/src/overlay.rs b/core/src/overlay.rs index b9f3c735..1fa994e4 100644 --- a/core/src/overlay.rs +++ b/core/src/overlay.rs @@ -38,7 +38,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ); /// Applies a [`widget::Operation`] to the [`Overlay`]. @@ -66,7 +66,7 @@ where &mut self, _event: Event, _layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, _shell: &mut Shell<'_, Message>, @@ -80,7 +80,7 @@ where fn mouse_interaction( &self, _layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { diff --git a/core/src/overlay/element.rs b/core/src/overlay/element.rs index 237d25d1..be67fc76 100644 --- a/core/src/overlay/element.rs +++ b/core/src/overlay/element.rs @@ -68,35 +68,25 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - self.overlay.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - shell, - ) + self.overlay + .on_event(event, layout, cursor, renderer, clipboard, shell) } /// Returns the current [`mouse::Interaction`] of the [`Element`]. pub fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - self.overlay.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + self.overlay + .mouse_interaction(layout, cursor, viewport, renderer) } /// Draws the [`Element`] and its children using the given [`Layout`]. @@ -106,10 +96,9 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { - self.overlay - .draw(renderer, theme, style, layout, cursor_position) + self.overlay.draw(renderer, theme, style, layout, cursor) } /// Applies a [`widget::Operation`] to the [`Element`]. @@ -215,7 +204,7 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, B>, @@ -226,7 +215,7 @@ where let event_status = self.content.on_event( event, layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -240,16 +229,12 @@ where fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - self.content.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + self.content + .mouse_interaction(layout, cursor, viewport, renderer) } fn draw( @@ -258,10 +243,9 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { - self.content - .draw(renderer, theme, style, layout, cursor_position) + self.content.draw(renderer, theme, style, layout, cursor) } fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool { diff --git a/core/src/overlay/group.rs b/core/src/overlay/group.rs index 0c48df34..e770abf8 100644 --- a/core/src/overlay/group.rs +++ b/core/src/overlay/group.rs @@ -81,7 +81,7 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -93,7 +93,7 @@ where child.on_event( event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -108,17 +108,17 @@ where theme: &<Renderer as crate::Renderer>::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { for (child, layout) in self.children.iter().zip(layout.children()) { - child.draw(renderer, theme, style, layout, cursor_position); + child.draw(renderer, theme, style, layout, cursor); } } fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -126,12 +126,7 @@ where .iter() .zip(layout.children()) .map(|(child, layout)| { - child.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + child.mouse_interaction(layout, cursor, viewport, renderer) }) .max() .unwrap_or_default() diff --git a/core/src/widget.rs b/core/src/widget.rs index 769f8659..79d86444 100644 --- a/core/src/widget.rs +++ b/core/src/widget.rs @@ -15,7 +15,7 @@ use crate::layout::{self, Layout}; use crate::mouse; use crate::overlay; use crate::renderer; -use crate::{Clipboard, Length, Point, Rectangle, Shell}; +use crate::{Clipboard, Length, Rectangle, Shell}; /// A component that displays information and allows interaction. /// @@ -67,7 +67,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ); @@ -111,7 +111,7 @@ where _state: &mut Tree, _event: Event, _layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, _shell: &mut Shell<'_, Message>, @@ -126,7 +126,7 @@ where &self, _state: &Tree, _layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 90af88b7..e934a2f5 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -1,12 +1,11 @@ //! Write some text for your users to read. use crate::alignment; use crate::layout; +use crate::mouse; use crate::renderer; use crate::text; use crate::widget::Tree; -use crate::{ - Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget, -}; +use crate::{Color, Element, Layout, Length, Pixels, Rectangle, Size, Widget}; use std::borrow::Cow; @@ -163,7 +162,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor_position: mouse::Cursor, _viewport: &Rectangle, ) { draw( diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index 80ad0b5b..df565859 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -1,8 +1,9 @@ use std::{f32::consts::PI, time::Instant}; use iced::executor; +use iced::mouse; use iced::widget::canvas::{ - self, stroke, Cache, Canvas, Cursor, Geometry, Path, Stroke, + self, stroke, Cache, Canvas, Geometry, Path, Stroke, }; use iced::{ Application, Command, Element, Length, Point, Rectangle, Renderer, @@ -78,7 +79,7 @@ impl<Message> canvas::Program<Message> for Arc { renderer: &Renderer, theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index f1c83a16..b4568cbf 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -61,9 +61,7 @@ impl Sandbox for Example { mod bezier { use iced::mouse; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - self, Canvas, Cursor, Frame, Geometry, Path, Stroke, - }; + use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke}; use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; #[derive(Default)] @@ -100,7 +98,7 @@ mod bezier { state: &mut Self::State, event: Event, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Curve>) { let cursor_position = if let Some(position) = cursor.position_in(&bounds) { @@ -155,7 +153,7 @@ mod bezier { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry> { let content = self.state.cache.draw( renderer, @@ -183,7 +181,7 @@ mod bezier { &self, _state: &Self::State, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> mouse::Interaction { if cursor.is_over(&bounds) { mouse::Interaction::Crosshair @@ -224,7 +222,7 @@ mod bezier { &self, renderer: &Renderer, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Geometry { let mut frame = Frame::new(renderer, bounds.size()); diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 6425e2da..fae77bc0 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,7 +1,6 @@ use iced::executor; -use iced::widget::canvas::{ - stroke, Cache, Cursor, Geometry, LineCap, Path, Stroke, -}; +use iced::mouse; +use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; use iced::{ Application, Color, Command, Element, Length, Point, Rectangle, Renderer, @@ -92,7 +91,7 @@ impl<Message> canvas::Program<Message, Renderer> for Clock { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let clock = self.clock.draw(renderer, bounds.size(), |frame| { let center = frame.center(); diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index de01099e..736a9d53 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -1,8 +1,10 @@ -use iced::widget::canvas::{self, Canvas, Cursor, Frame, Geometry, Path}; +use iced::alignment::{self, Alignment}; +use iced::mouse; +use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path}; use iced::widget::{column, row, text, Slider}; use iced::{ - alignment, Alignment, Color, Element, Length, Point, Rectangle, Renderer, - Sandbox, Settings, Size, Vector, + Color, Element, Length, Point, Rectangle, Renderer, Sandbox, Settings, + Size, Vector, }; use palette::{ self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue, @@ -246,7 +248,7 @@ impl<Message> canvas::Program<Message> for Theme { renderer: &Renderer, _theme: &iced::Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| { self.draw(frame); diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index b07f42ce..4b300116 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -3,7 +3,8 @@ mod quad { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{Color, Element, Length, Point, Rectangle, Size}; + use iced::mouse; + use iced::{Color, Element, Length, Rectangle, Size}; pub struct CustomQuad { size: f32, @@ -48,7 +49,7 @@ mod quad { _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { renderer.fill_quad( diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index 7854548c..713bc62d 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -12,7 +12,8 @@ mod circle { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{Color, Element, Length, Point, Rectangle, Size}; + use iced::mouse; + use iced::{Color, Element, Length, Rectangle, Size}; pub struct Circle { radius: f32, @@ -55,7 +56,7 @@ mod circle { _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { renderer.fill_quad( diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index eab8908b..aaa8efd1 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -204,15 +204,14 @@ fn view_controls<'a>( mod grid { use crate::Preset; + use iced::alignment; + use iced::mouse; use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - Cache, Canvas, Cursor, Frame, Geometry, Path, Text, - }; + use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text}; use iced::{ - alignment, mouse, Color, Element, Length, Point, Rectangle, Renderer, - Size, Theme, Vector, + Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, }; use rustc_hash::{FxHashMap, FxHashSet}; use std::future::Future; @@ -401,7 +400,7 @@ mod grid { interaction: &mut Interaction, event: Event, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event { *interaction = Interaction::None; @@ -539,7 +538,7 @@ mod grid { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry> { let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0); @@ -670,7 +669,7 @@ mod grid { &self, interaction: &Interaction, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> mouse::Interaction { match interaction { Interaction::Drawing => mouse::Interaction::Crosshair, diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index a4183db9..1f949d10 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -7,9 +7,8 @@ mod rainbow { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{ - Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, - }; + use iced::mouse; + use iced::{Element, Length, Rectangle, Renderer, Size, Theme, Vector}; #[derive(Debug, Clone, Copy, Default)] pub struct Rainbow; @@ -44,13 +43,13 @@ mod rainbow { _theme: &Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { use iced::advanced::Renderer as _; use iced_graphics::primitive::Mesh2D; - let b = layout.bounds(); + let bounds = layout.bounds(); // R O Y G B I V let color_r = [1.0, 0.0, 0.0, 1.0]; @@ -63,24 +62,24 @@ mod rainbow { let color_v = [0.75, 0.0, 0.5, 1.0]; let posn_center = { - if b.contains(cursor_position) { - [cursor_position.x - b.x, cursor_position.y - b.y] + if let Some(cursor_position) = cursor.position_in(&bounds) { + [cursor_position.x, cursor_position.y] } else { - [b.width / 2.0, b.height / 2.0] + [bounds.width / 2.0, bounds.height / 2.0] } }; let posn_tl = [0.0, 0.0]; - let posn_t = [b.width / 2.0, 0.0]; - let posn_tr = [b.width, 0.0]; - let posn_r = [b.width, b.height / 2.0]; - let posn_br = [b.width, b.height]; - let posn_b = [(b.width / 2.0), b.height]; - let posn_bl = [0.0, b.height]; - let posn_l = [0.0, b.height / 2.0]; + let posn_t = [bounds.width / 2.0, 0.0]; + let posn_tr = [bounds.width, 0.0]; + let posn_r = [bounds.width, bounds.height / 2.0]; + let posn_br = [bounds.width, bounds.height]; + let posn_b = [(bounds.width / 2.0), bounds.height]; + let posn_bl = [0.0, bounds.height]; + let posn_l = [0.0, bounds.height / 2.0]; let mesh = Primitive::SolidMesh { - size: b.size(), + size: bounds.size(), buffers: Mesh2D { vertices: vec![ ColoredVertex2D { @@ -133,9 +132,12 @@ mod rainbow { }, }; - renderer.with_translation(Vector::new(b.x, b.y), |renderer| { - renderer.draw_primitive(mesh); - }); + renderer.with_translation( + Vector::new(bounds.x, bounds.y), + |renderer| { + renderer.draw_primitive(mesh); + }, + ); } } diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 9e1e4c2f..82ed05d2 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -1,10 +1,11 @@ +use iced::executor; +use iced::keyboard; +use iced::subscription::{self, Subscription}; +use iced::theme; use iced::widget::{ self, button, column, container, horizontal_space, row, text, text_input, }; -use iced::{ - executor, keyboard, subscription, theme, Alignment, Application, Command, - Element, Event, Length, Settings, Subscription, -}; +use iced::{Alignment, Application, Command, Element, Event, Length, Settings}; use self::modal::Modal; @@ -254,7 +255,7 @@ mod modal { state: &mut widget::Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -263,7 +264,7 @@ mod modal { &mut state.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -277,7 +278,7 @@ mod modal { theme: &<Renderer as advanced::Renderer>::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.base.as_widget().draw( @@ -286,7 +287,7 @@ mod modal { theme, style, layout, - cursor_position, + cursor, viewport, ); } @@ -312,14 +313,14 @@ mod modal { &self, state: &widget::Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.base.as_widget().mouse_interaction( &state.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -377,7 +378,7 @@ mod modal { &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -389,7 +390,7 @@ mod modal { mouse::Button::Left, )) = &event { - if !content_bounds.contains(cursor_position) { + if !cursor.is_over(&content_bounds) { shell.publish(message.clone()); return event::Status::Captured; } @@ -400,7 +401,7 @@ mod modal { self.tree, event, layout.children().next().unwrap(), - cursor_position, + cursor, renderer, clipboard, shell, @@ -413,7 +414,7 @@ mod modal { theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { renderer.fill_quad( renderer::Quad { @@ -434,7 +435,7 @@ mod modal { theme, style, layout.children().next().unwrap(), - cursor_position, + cursor, &layout.bounds(), ); } @@ -456,14 +457,14 @@ mod modal { fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( self.tree, layout.children().next().unwrap(), - cursor_position, + cursor, viewport, renderer, ) diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs index 7df6c929..2830b78d 100644 --- a/examples/multitouch/src/main.rs +++ b/examples/multitouch/src/main.rs @@ -1,9 +1,10 @@ //! This example shows how to use touch events in `Canvas` to draw //! a circle around each fingertip. This only works on touch-enabled //! computers like Microsoft Surface. +use iced::mouse; use iced::widget::canvas::event; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{self, Canvas, Cursor, Geometry}; +use iced::widget::canvas::{self, Canvas, Geometry}; use iced::{ executor, touch, window, Application, Color, Command, Element, Length, Point, Rectangle, Renderer, Settings, Subscription, Theme, @@ -103,7 +104,7 @@ impl canvas::Program<Message, Renderer> for State { _state: &mut Self::State, event: event::Event, _bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { match event { event::Event::Touch(touch_event) => match touch_event { @@ -128,7 +129,7 @@ impl canvas::Program<Message, Renderer> for State { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { if self.fingers.len() < 2 { diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index 4faac6d6..ad681a91 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use iced::executor; +use iced::mouse; use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::{self, Canvas}; use iced::widget::{column, row, slider, text}; @@ -105,7 +106,7 @@ impl canvas::Program<Message> for SierpinskiGraph { _state: &mut Self::State, event: Event, bounds: Rectangle, - cursor: canvas::Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { let cursor_position = if let Some(position) = cursor.position_in(&bounds) { @@ -137,7 +138,7 @@ impl canvas::Program<Message> for SierpinskiGraph { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: canvas::Cursor, + _cursor: mouse::Cursor, ) -> Vec<canvas::Geometry> { let geom = self.cache.draw(renderer, bounds.size(), |frame| { frame.stroke( diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index d9e660d7..58d06206 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -8,11 +8,12 @@ //! [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations#An_animated_solar_system use iced::application; use iced::executor; +use iced::mouse; use iced::theme::{self, Theme}; use iced::widget::canvas; use iced::widget::canvas::gradient; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{Cursor, Path}; +use iced::widget::canvas::Path; use iced::window; use iced::{ Application, Color, Command, Element, Length, Point, Rectangle, Renderer, @@ -161,7 +162,7 @@ impl<Message> canvas::Program<Message> for State { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<canvas::Geometry> { use std::f32::consts::PI; diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index 515218e7..395cbc10 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -1,10 +1,10 @@ +use iced::executor; +use iced::keyboard; +use iced::subscription::{self, Subscription}; use iced::widget::{ self, button, column, container, pick_list, row, slider, text, text_input, }; -use iced::{ - executor, keyboard, subscription, Alignment, Application, Command, Element, - Event, Length, Settings, Subscription, -}; +use iced::{Alignment, Application, Command, Element, Event, Length, Settings}; use toast::{Status, Toast}; @@ -396,7 +396,7 @@ mod toast { state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -405,7 +405,7 @@ mod toast { &mut state.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -419,7 +419,7 @@ mod toast { theme: &Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( @@ -428,7 +428,7 @@ mod toast { theme, style, layout, - cursor_position, + cursor, viewport, ); } @@ -437,14 +437,14 @@ mod toast { &self, state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &state.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -523,7 +523,7 @@ mod toast { &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -572,7 +572,7 @@ mod toast { state, event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -595,7 +595,7 @@ mod toast { theme: &<Renderer as advanced::Renderer>::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let viewport = layout.bounds(); @@ -606,13 +606,7 @@ mod toast { .zip(layout.children()) { child.as_widget().draw( - state, - renderer, - theme, - style, - layout, - cursor_position, - &viewport, + state, renderer, theme, style, layout, cursor, &viewport, ); } } @@ -639,7 +633,7 @@ mod toast { fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -649,11 +643,7 @@ mod toast { .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget().mouse_interaction( - state, - layout, - cursor_position, - viewport, - renderer, + state, layout, cursor, viewport, renderer, ) }) .max() diff --git a/runtime/src/user_interface.rs b/runtime/src/user_interface.rs index d9206134..7dee13bc 100644 --- a/runtime/src/user_interface.rs +++ b/runtime/src/user_interface.rs @@ -203,7 +203,7 @@ where let event_status = overlay.on_event( event, Layout::new(&layout), - cursor_position, + mouse::Cursor::Available(cursor_position), renderer, clipboard, &mut shell, @@ -257,17 +257,17 @@ where .filter(|overlay| { overlay.is_over(Layout::new(&layout), cursor_position) }) - .map(|_| { - // TODO: Type-safe cursor availability - Point::new(-1.0, -1.0) - }) - .unwrap_or(cursor_position); + .map(|_| mouse::Cursor::Unavailable) + .unwrap_or(mouse::Cursor::Available(cursor_position)); self.overlay = Some(layout); (base_cursor, event_statuses) } else { - (cursor_position, vec![event::Status::Ignored; events.len()]) + ( + mouse::Cursor::Available(cursor_position), + vec![event::Status::Ignored; events.len()], + ) }; let _ = ManuallyDrop::into_inner(manual_overlay); @@ -427,19 +427,19 @@ where overlay.layout(renderer, self.bounds, Vector::ZERO) }); - let new_cursor_position = if overlay + let cursor = if overlay .is_over(Layout::new(&overlay_layout), cursor_position) { - Point::new(-1.0, -1.0) + mouse::Cursor::Unavailable } else { - cursor_position + mouse::Cursor::Available(cursor_position) }; self.overlay = Some(overlay_layout); - new_cursor_position + cursor } else { - cursor_position + mouse::Cursor::Available(cursor_position) }; self.root.as_widget().draw( @@ -455,7 +455,7 @@ where let base_interaction = self.root.as_widget().mouse_interaction( &self.state, Layout::new(&self.base), - cursor_position, + base_cursor, &viewport, renderer, ); @@ -480,7 +480,7 @@ where .map(|overlay| { let overlay_interaction = overlay.mouse_interaction( Layout::new(layout), - cursor_position, + mouse::Cursor::Available(cursor_position), &viewport, renderer, ); @@ -493,7 +493,7 @@ where theme, style, Layout::new(layout), - cursor_position, + mouse::Cursor::Available(cursor_position), ); }); @@ -230,7 +230,9 @@ pub mod keyboard { pub mod mouse { //! Listen and react to mouse events. - pub use crate::core::mouse::{Button, Event, Interaction, ScrollDelta}; + pub use crate::core::mouse::{ + Button, Cursor, Event, Interaction, ScrollDelta, + }; } pub mod subscription { diff --git a/widget/src/button.rs b/widget/src/button.rs index 70fed1d5..89af341c 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -187,7 +187,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -196,7 +196,7 @@ where &mut tree.children[0], event.clone(), layout.children().next().unwrap(), - cursor_position, + cursor, renderer, clipboard, shell, @@ -204,14 +204,9 @@ where return event::Status::Captured; } - update( - event, - layout, - cursor_position, - shell, - &self.on_press, - || tree.state.downcast_mut::<State>(), - ) + update(event, layout, cursor, shell, &self.on_press, || { + tree.state.downcast_mut::<State>() + }) } fn draw( @@ -221,7 +216,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); @@ -230,7 +225,7 @@ where let styling = draw( renderer, bounds, - cursor_position, + cursor, self.on_press.is_some(), theme, &self.style, @@ -245,7 +240,7 @@ where text_color: styling.text_color, }, content_layout, - cursor_position, + cursor, &bounds, ); } @@ -254,11 +249,11 @@ where &self, _tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction(layout, cursor_position, self.on_press.is_some()) + mouse_interaction(layout, cursor, self.on_press.is_some()) } fn overlay<'b>( @@ -305,7 +300,7 @@ impl State { pub fn update<'a, Message: Clone>( event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, on_press: &Option<Message>, state: impl FnOnce() -> &'a mut State, @@ -316,7 +311,7 @@ pub fn update<'a, Message: Clone>( if on_press.is_some() { let bounds = layout.bounds(); - if bounds.contains(cursor_position) { + if cursor.is_over(&bounds) { let state = state(); state.is_pressed = true; @@ -335,7 +330,7 @@ pub fn update<'a, Message: Clone>( let bounds = layout.bounds(); - if bounds.contains(cursor_position) { + if cursor.is_over(&bounds) { shell.publish(on_press); } @@ -358,7 +353,7 @@ pub fn update<'a, Message: Clone>( pub fn draw<'a, Renderer: crate::core::Renderer>( renderer: &mut Renderer, bounds: Rectangle, - cursor_position: Point, + cursor: mouse::Cursor, is_enabled: bool, style_sheet: &dyn StyleSheet< Style = <Renderer::Theme as StyleSheet>::Style, @@ -369,7 +364,7 @@ pub fn draw<'a, Renderer: crate::core::Renderer>( where Renderer::Theme: StyleSheet, { - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); let styling = if !is_enabled { style_sheet.disabled(style) @@ -442,10 +437,10 @@ pub fn layout<Renderer>( /// Returns the [`mouse::Interaction`] of a [`Button`]. pub fn mouse_interaction( layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, is_enabled: bool, ) -> mouse::Interaction { - let is_mouse_over = layout.bounds().contains(cursor_position); + let is_mouse_over = cursor.is_over(&layout.bounds()); if is_mouse_over && is_enabled { mouse::Interaction::Pointer diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs index 171c4534..96062038 100644 --- a/widget/src/canvas.rs +++ b/widget/src/canvas.rs @@ -1,10 +1,8 @@ //! Draw 2D graphics for your users. pub mod event; -mod cursor; mod program; -pub use cursor::Cursor; pub use event::Event; pub use program::Program; @@ -17,7 +15,7 @@ use crate::core::mouse; use crate::core::renderer; use crate::core::widget::tree::{self, Tree}; use crate::core::{Clipboard, Element, Shell, Widget}; -use crate::core::{Length, Point, Rectangle, Size, Vector}; +use crate::core::{Length, Rectangle, Size, Vector}; use crate::graphics::geometry; use std::marker::PhantomData; @@ -28,8 +26,9 @@ use std::marker::PhantomData; /// If you want to get a quick overview, here's how we can draw a simple circle: /// /// ```no_run -/// # use iced_widget::canvas::{self, Canvas, Cursor, Fill, Frame, Geometry, Path, Program}; +/// # use iced_widget::canvas::{self, Canvas, Fill, Frame, Geometry, Path, Program}; /// # use iced_widget::core::{Color, Rectangle}; +/// # use iced_widget::core::mouse; /// # use iced_widget::style::Theme; /// # /// # pub type Renderer = iced_widget::renderer::Renderer<Theme>; @@ -43,7 +42,7 @@ use std::marker::PhantomData; /// impl Program<()> for Circle { /// type State = (); /// -/// fn draw(&self, _state: &(), renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: 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()); /// @@ -144,7 +143,7 @@ where tree: &mut Tree, event: core::Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -160,8 +159,6 @@ where _ => None, }; - let cursor = Cursor::from_window_position(cursor_position); - if let Some(canvas_event) = canvas_event { let state = tree.state.downcast_mut::<P::State>(); @@ -182,12 +179,11 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { let bounds = layout.bounds(); - let cursor = Cursor::from_window_position(cursor_position); let state = tree.state.downcast_ref::<P::State>(); self.program.mouse_interaction(state, bounds, cursor) @@ -200,7 +196,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); @@ -209,7 +205,6 @@ where return; } - let cursor = Cursor::from_window_position(cursor_position); let state = tree.state.downcast_ref::<P::State>(); renderer.with_translation( diff --git a/widget/src/canvas/cursor.rs b/widget/src/canvas/cursor.rs deleted file mode 100644 index 5a65e9a7..00000000 --- a/widget/src/canvas/cursor.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::core::{Point, Rectangle}; - -/// The mouse cursor state. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Cursor { - /// The cursor has a defined position. - Available(Point), - - /// The cursor is currently unavailable (i.e. out of bounds or busy). - Unavailable, -} - -impl Cursor { - // TODO: Remove this once this type is used in `iced_native` to encode - // proper cursor availability - pub(crate) fn from_window_position(position: Point) -> Self { - if position.x < 0.0 || position.y < 0.0 { - Cursor::Unavailable - } else { - Cursor::Available(position) - } - } - - /// Returns the absolute position of the [`Cursor`], if available. - pub fn position(&self) -> Option<Point> { - match self { - Cursor::Available(position) => Some(*position), - Cursor::Unavailable => None, - } - } - - /// Returns the relative position of the [`Cursor`] inside the given bounds, - /// if available. - /// - /// If the [`Cursor`] is not over the provided bounds, this method will - /// return `None`. - pub fn position_in(&self, bounds: &Rectangle) -> Option<Point> { - if self.is_over(bounds) { - self.position_from(bounds.position()) - } else { - None - } - } - - /// Returns the relative position of the [`Cursor`] from the given origin, - /// if available. - pub fn position_from(&self, origin: Point) -> Option<Point> { - match self { - Cursor::Available(position) => { - Some(Point::new(position.x - origin.x, position.y - origin.y)) - } - Cursor::Unavailable => None, - } - } - - /// Returns whether the [`Cursor`] is currently over the provided bounds - /// or not. - pub fn is_over(&self, bounds: &Rectangle) -> bool { - match self { - Cursor::Available(position) => bounds.contains(*position), - Cursor::Unavailable => false, - } - } -} diff --git a/widget/src/canvas/program.rs b/widget/src/canvas/program.rs index ad0fbb83..929ee285 100644 --- a/widget/src/canvas/program.rs +++ b/widget/src/canvas/program.rs @@ -1,6 +1,5 @@ use crate::canvas::event::{self, Event}; use crate::canvas::mouse; -use crate::canvas::Cursor; use crate::core::Rectangle; use crate::graphics::geometry::{self, Geometry}; @@ -33,7 +32,7 @@ where _state: &mut Self::State, _event: Event, _bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { (event::Status::Ignored, None) } @@ -51,7 +50,7 @@ where renderer: &Renderer, theme: &Renderer::Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry>; /// Returns the current mouse interaction of the [`Program`]. @@ -64,7 +63,7 @@ where &self, _state: &Self::State, _bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> mouse::Interaction { mouse::Interaction::default() } @@ -82,7 +81,7 @@ where state: &mut Self::State, event: Event, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { T::update(self, state, event, bounds, cursor) } @@ -93,7 +92,7 @@ where renderer: &Renderer, theme: &Renderer::Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry> { T::draw(self, state, renderer, theme, bounds, cursor) } @@ -102,7 +101,7 @@ where &self, state: &Self::State, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> mouse::Interaction { T::mouse_interaction(self, state, bounds, cursor) } diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 4c8a989b..86f573dd 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -8,8 +8,8 @@ use crate::core::text; use crate::core::touch; use crate::core::widget::Tree; use crate::core::{ - Alignment, Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, - Shell, Widget, + Alignment, Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, + Widget, }; use crate::{Row, Text}; @@ -204,7 +204,7 @@ where _tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -212,7 +212,7 @@ where match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - let mouse_over = layout.bounds().contains(cursor_position); + let mouse_over = cursor.is_over(&layout.bounds()); if mouse_over { shell.publish((self.on_toggle)(!self.is_checked)); @@ -230,11 +230,11 @@ where &self, _tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - if layout.bounds().contains(cursor_position) { + if cursor.is_over(&layout.bounds()) { mouse::Interaction::Pointer } else { mouse::Interaction::default() @@ -248,11 +248,10 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { - let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&layout.bounds()); let mut children = layout.children(); diff --git a/widget/src/column.rs b/widget/src/column.rs index 8f363ec6..d92d794b 100644 --- a/widget/src/column.rs +++ b/widget/src/column.rs @@ -6,8 +6,8 @@ use crate::core::overlay; use crate::core::renderer; use crate::core::widget::{Operation, Tree}; use crate::core::{ - Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Point, - Rectangle, Shell, Widget, + Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, + Shell, Widget, }; /// A container that distributes its contents vertically. @@ -166,7 +166,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -180,7 +180,7 @@ where state, event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -193,7 +193,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -203,11 +203,7 @@ where .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget().mouse_interaction( - state, - layout, - cursor_position, - viewport, - renderer, + state, layout, cursor, viewport, renderer, ) }) .max() @@ -221,7 +217,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { for ((child, state), layout) in self @@ -230,15 +226,9 @@ where .zip(&tree.children) .zip(layout.children()) { - child.as_widget().draw( - state, - renderer, - theme, - style, - layout, - cursor_position, - viewport, - ); + child + .as_widget() + .draw(state, renderer, theme, style, layout, cursor, viewport); } } diff --git a/widget/src/container.rs b/widget/src/container.rs index 13e76551..da9a31d6 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -196,7 +196,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -205,7 +205,7 @@ where &mut tree.children[0], event, layout.children().next().unwrap(), - cursor_position, + cursor, renderer, clipboard, shell, @@ -216,14 +216,14 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &tree.children[0], layout.children().next().unwrap(), - cursor_position, + cursor, viewport, renderer, ) @@ -236,7 +236,7 @@ where theme: &Renderer::Theme, renderer_style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { let style = theme.appearance(&self.style); @@ -253,7 +253,7 @@ where .unwrap_or(renderer_style.text_color), }, layout.children().next().unwrap(), - cursor_position, + cursor, viewport, ); } diff --git a/widget/src/image.rs b/widget/src/image.rs index abcb6ef2..66bf2156 100644 --- a/widget/src/image.rs +++ b/widget/src/image.rs @@ -4,10 +4,11 @@ pub use viewer::Viewer; use crate::core::image; use crate::core::layout; +use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; use crate::core::{ - ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget, + ContentFit, Element, Layout, Length, Rectangle, Size, Vector, Widget, }; use std::hash::Hash; @@ -186,7 +187,7 @@ where _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { draw(renderer, layout, &self.handle, self.content_fit) diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs index 0d60d818..a2ee1e5c 100644 --- a/widget/src/image/viewer.rs +++ b/widget/src/image/viewer.rs @@ -144,18 +144,19 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, _clipboard: &mut dyn Clipboard, _shell: &mut Shell<'_, Message>, ) -> event::Status { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); match event { - Event::Mouse(mouse::Event::WheelScrolled { delta }) - if is_mouse_over => - { + Event::Mouse(mouse::Event::WheelScrolled { delta }) => { + let Some(cursor_position) = cursor.position() else { + return event::Status::Ignored; + }; + match delta { mouse::ScrollDelta::Lines { y, .. } | mouse::ScrollDelta::Pixels { y, .. } => { @@ -205,9 +206,11 @@ where event::Status::Captured } - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - if is_mouse_over => - { + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { + let Some(cursor_position) = cursor.position() else { + return event::Status::Ignored; + }; + let state = tree.state.downcast_mut::<State>(); state.cursor_grabbed_at = Some(cursor_position); @@ -277,13 +280,13 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { let state = tree.state.downcast_ref::<State>(); let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); if state.is_cursor_grabbed() { mouse::Interaction::Grabbing @@ -301,7 +304,7 @@ where _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { let state = tree.state.downcast_ref::<State>(); diff --git a/widget/src/lazy.rs b/widget/src/lazy.rs index 0ad46865..92a611c3 100644 --- a/widget/src/lazy.rs +++ b/widget/src/lazy.rs @@ -181,7 +181,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -191,7 +191,7 @@ where &mut tree.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -203,7 +203,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -211,7 +211,7 @@ where element.as_widget().mouse_interaction( &tree.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -225,7 +225,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.with_element(|element| { @@ -235,7 +235,7 @@ where theme, style, layout, - cursor_position, + cursor, viewport, ) }) @@ -342,27 +342,22 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let _ = self.with_overlay_maybe(|overlay| { - overlay.draw(renderer, theme, style, layout, cursor_position); + overlay.draw(renderer, theme, style, layout, cursor); }); } fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.with_overlay_maybe(|overlay| { - overlay.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + overlay.mouse_interaction(layout, cursor, viewport, renderer) }) .unwrap_or_default() } @@ -371,20 +366,13 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { self.with_overlay_mut_maybe(|overlay| { - overlay.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - shell, - ) + overlay.on_event(event, layout, cursor, renderer, clipboard, shell) }) .unwrap_or(event::Status::Ignored) } diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs index 49ae68af..f462c8cf 100644 --- a/widget/src/lazy/component.rs +++ b/widget/src/lazy/component.rs @@ -265,7 +265,7 @@ where tree: &mut Tree, event: core::Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -279,7 +279,7 @@ where &mut t.borrow_mut().as_mut().unwrap().children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -397,7 +397,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>(); @@ -408,7 +408,7 @@ where theme, style, layout, - cursor_position, + cursor, viewport, ); }); @@ -418,7 +418,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -427,7 +427,7 @@ where element.as_widget().mouse_interaction( &tree.borrow().as_ref().unwrap().children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -569,27 +569,22 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let _ = self.with_overlay_maybe(|overlay| { - overlay.draw(renderer, theme, style, layout, cursor_position); + overlay.draw(renderer, theme, style, layout, cursor); }); } fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.with_overlay_maybe(|overlay| { - overlay.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + overlay.mouse_interaction(layout, cursor, viewport, renderer) }) .unwrap_or_default() } @@ -598,7 +593,7 @@ where &mut self, event: core::Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -611,7 +606,7 @@ where overlay.on_event( event, layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs index 9b4fd9dd..bd6385bc 100644 --- a/widget/src/lazy/responsive.rs +++ b/widget/src/lazy/responsive.rs @@ -177,7 +177,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -198,7 +198,7 @@ where tree, event, layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -222,7 +222,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { let state = tree.state.downcast_ref::<State>(); @@ -235,13 +235,7 @@ where &self.view, |tree, renderer, layout, element| { element.as_widget().draw( - tree, - renderer, - theme, - style, - layout, - cursor_position, - viewport, + tree, renderer, theme, style, layout, cursor, viewport, ) }, ) @@ -251,7 +245,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -264,13 +258,9 @@ where layout, &self.view, |tree, renderer, layout, element| { - element.as_widget().mouse_interaction( - tree, - layout, - cursor_position, - viewport, - renderer, - ) + element + .as_widget() + .mouse_interaction(tree, layout, cursor, viewport, renderer) }, ) } @@ -384,27 +374,22 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let _ = self.with_overlay_maybe(|overlay| { - overlay.draw(renderer, theme, style, layout, cursor_position); + overlay.draw(renderer, theme, style, layout, cursor); }); } fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.with_overlay_maybe(|overlay| { - overlay.mouse_interaction( - layout, - cursor_position, - viewport, - renderer, - ) + overlay.mouse_interaction(layout, cursor, viewport, renderer) }) .unwrap_or_default() } @@ -413,20 +398,13 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { self.with_overlay_mut_maybe(|overlay| { - overlay.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - shell, - ) + overlay.on_event(event, layout, cursor, renderer, clipboard, shell) }) .unwrap_or(event::Status::Ignored) } diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index 0232c494..423f070c 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -8,7 +8,7 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::{tree, Operation, Tree}; use crate::core::{ - Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget, + Clipboard, Element, Layout, Length, Rectangle, Shell, Widget, }; /// Emit messages on mouse events. @@ -146,7 +146,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -155,7 +155,7 @@ where &mut tree.children[0], event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -163,21 +163,21 @@ where return event::Status::Captured; } - update(self, &event, layout, cursor_position, shell) + update(self, &event, layout, cursor, shell) } fn mouse_interaction( &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &tree.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -190,7 +190,7 @@ where theme: &Renderer::Theme, renderer_style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( @@ -199,7 +199,7 @@ where theme, renderer_style, layout, - cursor_position, + cursor, viewport, ); } @@ -237,10 +237,10 @@ fn update<Message: Clone, Renderer>( widget: &mut MouseArea<'_, Message, Renderer>, event: &Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, ) -> event::Status { - if !layout.bounds().contains(cursor_position) { + if !cursor.is_over(&layout.bounds()) { return event::Status::Ignored; } diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 84cc800c..fe1175ac 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -259,36 +259,25 @@ where &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { self.container.on_event( - self.state, - event, - layout, - cursor_position, - renderer, - clipboard, - shell, + self.state, event, layout, cursor, renderer, clipboard, shell, ) } fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - self.container.mouse_interaction( - self.state, - layout, - cursor_position, - viewport, - renderer, - ) + self.container + .mouse_interaction(self.state, layout, cursor, viewport, renderer) } fn draw( @@ -297,7 +286,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let appearance = theme.appearance(&self.style); let bounds = layout.bounds(); @@ -312,15 +301,8 @@ where appearance.background, ); - self.container.draw( - self.state, - renderer, - theme, - style, - layout, - cursor_position, - &bounds, - ); + self.container + .draw(self.state, renderer, theme, style, layout, cursor, &bounds); } } @@ -387,7 +369,7 @@ where _state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, _clipboard: &mut dyn Clipboard, _shell: &mut Shell<'_, Message>, @@ -396,7 +378,7 @@ where Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { let bounds = layout.bounds(); - if bounds.contains(cursor_position) { + if cursor.is_over(&bounds) { if let Some(index) = *self.hovered_option { if let Some(option) = self.options.get(index) { *self.last_selection = Some(option.clone()); @@ -405,9 +387,9 @@ where } } Event::Mouse(mouse::Event::CursorMoved { .. }) => { - let bounds = layout.bounds(); - - if bounds.contains(cursor_position) { + if let Some(cursor_position) = + cursor.position_in(&layout.bounds()) + { let text_size = self .text_size .unwrap_or_else(|| renderer.default_size()); @@ -416,16 +398,14 @@ where self.text_line_height.to_absolute(Pixels(text_size)), ) + self.padding.vertical(); - *self.hovered_option = Some( - ((cursor_position.y - bounds.y) / option_height) - as usize, - ); + *self.hovered_option = + Some((cursor_position.y / option_height) as usize); } } Event::Touch(touch::Event::FingerPressed { .. }) => { - let bounds = layout.bounds(); - - if bounds.contains(cursor_position) { + if let Some(cursor_position) = + cursor.position_in(&layout.bounds()) + { let text_size = self .text_size .unwrap_or_else(|| renderer.default_size()); @@ -434,10 +414,8 @@ where self.text_line_height.to_absolute(Pixels(text_size)), ) + self.padding.vertical(); - *self.hovered_option = Some( - ((cursor_position.y - bounds.y) / option_height) - as usize, - ); + *self.hovered_option = + Some((cursor_position.y / option_height) as usize); if let Some(index) = *self.hovered_option { if let Some(option) = self.options.get(index) { @@ -456,11 +434,11 @@ where &self, _state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - let is_mouse_over = layout.bounds().contains(cursor_position); + let is_mouse_over = cursor.is_over(&layout.bounds()); if is_mouse_over { mouse::Interaction::Pointer @@ -476,7 +454,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, viewport: &Rectangle, ) { let appearance = theme.appearance(&self.style); diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 7bddc4a6..7e0198fe 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -313,7 +313,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -331,7 +331,7 @@ where self.contents.layout(), &event, layout, - cursor_position, + cursor, shell, self.spacing, self.contents.iter(), @@ -353,7 +353,7 @@ where tree, event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -367,7 +367,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -375,7 +375,7 @@ where tree.state.downcast_ref(), self.contents.layout(), layout, - cursor_position, + cursor, self.spacing, self.on_resize.as_ref().map(|(leeway, _)| *leeway), ) @@ -388,7 +388,7 @@ where content.mouse_interaction( tree, layout, - cursor_position, + cursor, viewport, renderer, self.drag_enabled(), @@ -406,14 +406,14 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { draw( tree.state.downcast_ref(), self.contents.layout(), layout, - cursor_position, + cursor, renderer, theme, style, @@ -425,20 +425,9 @@ where .iter() .zip(&tree.children) .map(|((pane, content), tree)| (pane, (content, tree))), - |(content, tree), - renderer, - style, - layout, - cursor_position, - rectangle| { + |(content, tree), renderer, style, layout, cursor, rectangle| { content.draw( - tree, - renderer, - theme, - style, - layout, - cursor_position, - rectangle, + tree, renderer, theme, style, layout, cursor, rectangle, ); }, ) @@ -520,7 +509,7 @@ pub fn update<'a, Message, T: Draggable>( node: &Node, event: &Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, spacing: f32, contents: impl Iterator<Item = (Pane, T)>, @@ -535,7 +524,7 @@ pub fn update<'a, Message, T: Draggable>( | Event::Touch(touch::Event::FingerPressed { .. }) => { let bounds = layout.bounds(); - if bounds.contains(cursor_position) { + if let Some(cursor_position) = cursor.position_over(&bounds) { event_status = event::Status::Captured; match on_resize { @@ -592,14 +581,18 @@ 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 = contents - .zip(layout.children()) - .filter_map(|(target, layout)| { - layout_region(layout, cursor_position) - .map(|region| (target, region)) + let dropped_region = + cursor.position().and_then(|cursor_position| { + contents + .zip(layout.children()) + .filter_map(|(target, layout)| { + layout_region(layout, cursor_position) + .map(|region| (target, region)) + }) + .next() }); - let event = match dropped_region.next() { + let event = match dropped_region { Some(((target, _), region)) if pane != target => { DragEvent::Dropped { pane, @@ -634,24 +627,32 @@ pub fn update<'a, Message, T: Draggable>( ); if let Some((axis, rectangle, _)) = splits.get(&split) { - let ratio = match axis { - Axis::Horizontal => { - let position = - cursor_position.y - bounds.y - rectangle.y; - - (position / rectangle.height).clamp(0.1, 0.9) - } - Axis::Vertical => { - let position = - cursor_position.x - bounds.x - rectangle.x; - - (position / rectangle.width).clamp(0.1, 0.9) - } - }; - - shell.publish(on_resize(ResizeEvent { split, ratio })); - - event_status = event::Status::Captured; + if let Some(cursor_position) = cursor.position() { + let ratio = match axis { + Axis::Horizontal => { + let position = cursor_position.y + - bounds.y + - rectangle.y; + + (position / rectangle.height) + .clamp(0.1, 0.9) + } + Axis::Vertical => { + let position = cursor_position.x + - bounds.x + - rectangle.x; + + (position / rectangle.width).clamp(0.1, 0.9) + } + }; + + shell.publish(on_resize(ResizeEvent { + split, + ratio, + })); + + event_status = event::Status::Captured; + } } } } @@ -724,7 +725,7 @@ pub fn mouse_interaction( action: &state::Action, node: &Node, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, spacing: f32, resize_leeway: Option<f32>, ) -> Option<mouse::Interaction> { @@ -735,6 +736,7 @@ pub fn mouse_interaction( let resize_axis = action.picked_split().map(|(_, axis)| axis).or_else(|| { resize_leeway.and_then(|leeway| { + let cursor_position = cursor.position()?; let bounds = layout.bounds(); let splits = node.split_regions(spacing, bounds.size()); @@ -764,7 +766,7 @@ pub fn draw<Renderer, T>( action: &state::Action, node: &Node, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &mut Renderer, theme: &Renderer::Theme, default_style: &renderer::Style, @@ -778,7 +780,7 @@ pub fn draw<Renderer, T>( &mut Renderer, &renderer::Style, Layout<'_>, - Point, + mouse::Cursor, &Rectangle, ), ) where @@ -802,6 +804,7 @@ pub fn draw<Renderer, T>( }) .or_else(|| match resize_leeway { Some(leeway) => { + let cursor_position = cursor.position()?; let bounds = layout.bounds(); let relative_cursor = Point::new( @@ -822,12 +825,10 @@ pub fn draw<Renderer, T>( None => None, }); - let pane_cursor_position = if picked_pane.is_some() { - // TODO: Remove once cursor availability is encoded in the type - // system - Point::new(-1.0, -1.0) + let pane_cursor = if picked_pane.is_some() { + mouse::Cursor::Unavailable } else { - cursor_position + cursor }; let mut render_picked_pane = None; @@ -843,12 +844,15 @@ pub fn draw<Renderer, T>( renderer, default_style, layout, - pane_cursor_position, + pane_cursor, viewport, ); if picked_pane.is_some() { - if let Some(region) = layout_region(layout, cursor_position) + if let Some(region) = + cursor.position().and_then(|cursor_position| { + layout_region(layout, cursor_position) + }) { let bounds = layout_region_bounds(layout, region); let hovered_region_style = theme.hovered_region(style); @@ -872,7 +876,7 @@ pub fn draw<Renderer, T>( renderer, default_style, layout, - pane_cursor_position, + pane_cursor, viewport, ); } @@ -881,25 +885,27 @@ pub fn draw<Renderer, T>( // Render picked pane last if let Some((pane, origin, layout)) = render_picked_pane { - let bounds = layout.bounds(); - - renderer.with_translation( - cursor_position - - Point::new(bounds.x + origin.x, bounds.y + origin.y), - |renderer| { - renderer.with_layer(bounds, |renderer| { - draw_pane( - pane, - renderer, - default_style, - layout, - pane_cursor_position, - viewport, - ); - }); - }, - ); - }; + if let Some(cursor_position) = cursor.position() { + let bounds = layout.bounds(); + + renderer.with_translation( + cursor_position + - Point::new(bounds.x + origin.x, bounds.y + origin.y), + |renderer| { + renderer.with_layer(bounds, |renderer| { + draw_pane( + pane, + renderer, + default_style, + layout, + pane_cursor, + viewport, + ); + }); + }, + ); + } + } if let Some((axis, split_region, is_picked)) = picked_split { let highlight = if is_picked { diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index 035ef05b..fe5c6af0 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -95,7 +95,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { use container::StyleSheet; @@ -113,7 +113,7 @@ where let title_bar_layout = children.next().unwrap(); let body_layout = children.next().unwrap(); - let show_controls = bounds.contains(cursor_position); + let show_controls = cursor.is_over(&bounds); self.body.as_widget().draw( &tree.children[0], @@ -121,7 +121,7 @@ where theme, style, body_layout, - cursor_position, + cursor, viewport, ); @@ -131,7 +131,7 @@ where theme, style, title_bar_layout, - cursor_position, + cursor, viewport, show_controls, ); @@ -142,7 +142,7 @@ where theme, style, layout, - cursor_position, + cursor, viewport, ); } @@ -218,7 +218,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -233,7 +233,7 @@ where &mut tree.children[1], event.clone(), children.next().unwrap(), - cursor_position, + cursor, renderer, clipboard, shell, @@ -251,7 +251,7 @@ where &mut tree.children[0], event, body_layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -265,42 +265,48 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, drag_enabled: bool, ) -> mouse::Interaction { - let (body_layout, title_bar_interaction) = - if let Some(title_bar) = &self.title_bar { - let mut children = layout.children(); - let title_bar_layout = children.next().unwrap(); - - let is_over_pick_area = title_bar - .is_over_pick_area(title_bar_layout, cursor_position); - - if is_over_pick_area && drag_enabled { - return mouse::Interaction::Grab; - } - - let mouse_interaction = title_bar.mouse_interaction( - &tree.children[1], - title_bar_layout, - cursor_position, - viewport, - renderer, - ); + let (body_layout, title_bar_interaction) = if let Some(title_bar) = + &self.title_bar + { + let mut children = layout.children(); + let title_bar_layout = children.next().unwrap(); + + let is_over_pick_area = cursor + .position() + .map(|cursor_position| { + title_bar + .is_over_pick_area(title_bar_layout, cursor_position) + }) + .unwrap_or_default(); + + if is_over_pick_area && drag_enabled { + return mouse::Interaction::Grab; + } - (children.next().unwrap(), mouse_interaction) - } else { - (layout, mouse::Interaction::default()) - }; + let mouse_interaction = title_bar.mouse_interaction( + &tree.children[1], + title_bar_layout, + cursor, + viewport, + renderer, + ); + + (children.next().unwrap(), mouse_interaction) + } else { + (layout, mouse::Interaction::default()) + }; self.body .as_widget() .mouse_interaction( &tree.children[0], body_layout, - cursor_position, + cursor, viewport, renderer, ) diff --git a/widget/src/pane_grid/draggable.rs b/widget/src/pane_grid/draggable.rs index a9274dad..9d31feb5 100644 --- a/widget/src/pane_grid/draggable.rs +++ b/widget/src/pane_grid/draggable.rs @@ -4,9 +4,5 @@ use crate::core::{Layout, Point}; pub trait Draggable { /// Returns whether the [`Draggable`] with the given [`Layout`] can be picked /// at the provided cursor position. - fn can_be_dragged_at( - &self, - layout: Layout<'_>, - cursor_position: Point, - ) -> bool; + fn can_be_dragged_at(&self, layout: Layout<'_>, cursor: Point) -> bool; } diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs index 2129937b..2fe79f80 100644 --- a/widget/src/pane_grid/title_bar.rs +++ b/widget/src/pane_grid/title_bar.rs @@ -122,7 +122,7 @@ where theme: &Renderer::Theme, inherited_style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, show_controls: bool, ) { @@ -158,7 +158,7 @@ where theme, &inherited_style, controls_layout, - cursor_position, + cursor, viewport, ); } @@ -171,7 +171,7 @@ where theme, &inherited_style, title_layout, - cursor_position, + cursor, viewport, ); } @@ -300,7 +300,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -324,7 +324,7 @@ where &mut tree.children[1], event.clone(), controls_layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -338,7 +338,7 @@ where &mut tree.children[0], event, title_layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -354,7 +354,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -367,7 +367,7 @@ where let title_interaction = self.content.as_widget().mouse_interaction( &tree.children[0], title_layout, - cursor_position, + cursor, viewport, renderer, ); @@ -377,7 +377,7 @@ where let controls_interaction = controls.as_widget().mouse_interaction( &tree.children[1], controls_layout, - cursor_position, + cursor, viewport, renderer, ); diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index dcd0629b..d1c03bcd 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -11,8 +11,8 @@ use crate::core::text::{self, Text}; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Element, Layout, Length, Padding, Pixels, Point, Rectangle, - Shell, Size, Widget, + Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, Shell, + Size, Widget, }; use crate::overlay::menu::{self, Menu}; use crate::scrollable; @@ -196,7 +196,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -204,7 +204,7 @@ where update( event, layout, - cursor_position, + cursor, shell, self.on_selected.as_ref(), self.selected.as_ref(), @@ -217,11 +217,11 @@ where &self, _tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction(layout, cursor_position) + mouse_interaction(layout, cursor) } fn draw( @@ -231,7 +231,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { let font = self.font.unwrap_or_else(|| renderer.default_font()); @@ -239,7 +239,7 @@ where renderer, theme, layout, - cursor_position, + cursor, self.padding, self.text_size, self.text_line_height, @@ -431,7 +431,7 @@ where pub fn update<'a, T, Message>( event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, on_selected: &dyn Fn(T) -> Message, selected: Option<&T>, @@ -452,7 +452,7 @@ where state.is_open = false; event::Status::Captured - } else if layout.bounds().contains(cursor_position) { + } else if cursor.is_over(&layout.bounds()) { state.is_open = true; state.hovered_option = options.iter().position(|option| Some(option) == selected); @@ -478,7 +478,7 @@ where let state = state(); if state.keyboard_modifiers.command() - && layout.bounds().contains(cursor_position) + && cursor.is_over(&layout.bounds()) && !state.is_open { fn find_next<'a, T: PartialEq>( @@ -529,10 +529,10 @@ where /// Returns the current [`mouse::Interaction`] of a [`PickList`]. pub fn mouse_interaction( layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) -> mouse::Interaction { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); if is_mouse_over { mouse::Interaction::Pointer @@ -593,7 +593,7 @@ pub fn draw<'a, T, Renderer>( renderer: &mut Renderer, theme: &Renderer::Theme, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, padding: Padding, text_size: Option<f32>, text_line_height: text::LineHeight, @@ -610,7 +610,7 @@ pub fn draw<'a, T, Renderer>( T: ToString + 'a, { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); let is_selected = selected.is_some(); let style = if is_mouse_over { diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 9e1e9131..37c6bc72 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -1,10 +1,9 @@ //! Provide progress feedback to your users. use crate::core::layout; +use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{ - Color, Element, Layout, Length, Point, Rectangle, Size, Widget, -}; +use crate::core::{Color, Element, Layout, Length, Rectangle, Size, Widget}; use std::ops::RangeInclusive; @@ -115,7 +114,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs index 7709125f..06be93c0 100644 --- a/widget/src/qr_code.rs +++ b/widget/src/qr_code.rs @@ -1,6 +1,7 @@ //! Encode and display information in a QR code. use crate::canvas; use crate::core::layout; +use crate::core::mouse; use crate::core::renderer::{self, Renderer as _}; use crate::core::widget::Tree; use crate::core::{ @@ -74,7 +75,7 @@ impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> { _theme: &Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); diff --git a/widget/src/radio.rs b/widget/src/radio.rs index 9dad1e22..9c954275 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -8,8 +8,8 @@ use crate::core::text; use crate::core::touch; use crate::core::widget::Tree; use crate::core::{ - Alignment, Clipboard, Color, Element, Layout, Length, Pixels, Point, - Rectangle, Shell, Widget, + Alignment, Clipboard, Color, Element, Layout, Length, Pixels, Rectangle, + Shell, Widget, }; use crate::{Row, Text}; @@ -229,7 +229,7 @@ where _state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -237,7 +237,7 @@ where match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if layout.bounds().contains(cursor_position) { + if cursor.is_over(&layout.bounds()) { shell.publish(self.on_click.clone()); return event::Status::Captured; @@ -253,11 +253,11 @@ where &self, _state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - if layout.bounds().contains(cursor_position) { + if cursor.is_over(&layout.bounds()) { mouse::Interaction::Pointer } else { mouse::Interaction::default() @@ -271,11 +271,10 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { - let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&layout.bounds()); let mut children = layout.children(); diff --git a/widget/src/row.rs b/widget/src/row.rs index 3ce363f8..1db22416 100644 --- a/widget/src/row.rs +++ b/widget/src/row.rs @@ -6,8 +6,8 @@ use crate::core::overlay; use crate::core::renderer; use crate::core::widget::{Operation, Tree}; use crate::core::{ - Alignment, Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, - Shell, Widget, + Alignment, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, + Widget, }; /// A container that distributes its contents horizontally. @@ -155,7 +155,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -169,7 +169,7 @@ where state, event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -182,7 +182,7 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -192,11 +192,7 @@ where .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget().mouse_interaction( - state, - layout, - cursor_position, - viewport, - renderer, + state, layout, cursor, viewport, renderer, ) }) .max() @@ -210,7 +206,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { for ((child, state), layout) in self @@ -219,15 +215,9 @@ where .zip(&tree.children) .zip(layout.children()) { - child.as_widget().draw( - state, - renderer, - theme, - style, - layout, - cursor_position, - viewport, - ); + child + .as_widget() + .draw(state, renderer, theme, style, layout, cursor, viewport); } } diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 272bd2b3..d703e6ae 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -1,9 +1,10 @@ //! Display a horizontal or vertical rule for dividing content. use crate::core::layout; +use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; use crate::core::{ - Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget, + Color, Element, Layout, Length, Pixels, Rectangle, Size, Widget, }; pub use crate::style::rule::{Appearance, FillMode, StyleSheet}; @@ -86,7 +87,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 12e544c5..e5cda4df 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -222,7 +222,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -231,18 +231,18 @@ where tree.state.downcast_mut::<State>(), event, layout, - cursor_position, + cursor, clipboard, shell, &self.vertical, self.horizontal.as_ref(), &self.on_scroll, - |event, layout, cursor_position, clipboard, shell| { + |event, layout, cursor, clipboard, shell| { self.content.as_widget_mut().on_event( &mut tree.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -258,7 +258,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { draw( @@ -266,18 +266,18 @@ where renderer, theme, layout, - cursor_position, + cursor, &self.vertical, self.horizontal.as_ref(), &self.style, - |renderer, layout, cursor_position, viewport| { + |renderer, layout, cursor, viewport| { self.content.as_widget().draw( &tree.children[0], renderer, theme, style, layout, - cursor_position, + cursor, viewport, ) }, @@ -288,21 +288,21 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { mouse_interaction( tree.state.downcast_ref::<State>(), layout, - cursor_position, + cursor, &self.vertical, self.horizontal.as_ref(), - |layout, cursor_position, viewport| { + |layout, cursor, viewport| { self.content.as_widget().mouse_interaction( &tree.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -428,7 +428,7 @@ pub fn update<Message>( state: &mut State, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, vertical: &Properties, @@ -437,13 +437,13 @@ pub fn update<Message>( update_content: impl FnOnce( Event, Layout<'_>, - Point, + mouse::Cursor, &mut dyn Clipboard, &mut Shell<'_, Message>, ) -> event::Status, ) -> event::Status { let bounds = layout.bounds(); - let mouse_over_scrollable = bounds.contains(cursor_position); + let cursor_over_scrollable = cursor.position_over(&bounds); let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); @@ -452,28 +452,21 @@ pub fn update<Message>( Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = - scrollbars.is_mouse_over(cursor_position); + scrollbars.is_mouse_over(cursor); let event_status = { - let cursor_position = if mouse_over_scrollable - && !(mouse_over_y_scrollbar || mouse_over_x_scrollbar) - { - cursor_position + state.offset(bounds, content_bounds) - } else { - // TODO: Make `cursor_position` an `Option<Point>` so we can encode - // cursor availability. - // This will probably happen naturally once we add multi-window - // support. - Point::new(-1.0, -1.0) + let cursor = match cursor_over_scrollable { + Some(cursor_position) + if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => + { + mouse::Cursor::Available( + cursor_position + state.offset(bounds, content_bounds), + ) + } + _ => mouse::Cursor::Unavailable, }; - update_content( - event.clone(), - content, - cursor_position, - clipboard, - shell, - ) + update_content(event.clone(), content, cursor, clipboard, shell) }; if let event::Status::Captured = event_status { @@ -487,76 +480,71 @@ pub fn update<Message>( return event::Status::Ignored; } - if mouse_over_scrollable { - match event { - Event::Mouse(mouse::Event::WheelScrolled { delta }) => { - let delta = match delta { - mouse::ScrollDelta::Lines { x, y } => { - // TODO: Configurable speed/friction (?) - let movement = if state.keyboard_modifiers.shift() { - Vector::new(y, x) - } else { - Vector::new(x, y) - }; - - movement * 60.0 - } - mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y), - }; + let Some(cursor_position) = cursor_over_scrollable else { + return event::Status::Ignored + }; + + match event { + Event::Mouse(mouse::Event::WheelScrolled { delta }) => { + let delta = match delta { + mouse::ScrollDelta::Lines { x, y } => { + // TODO: Configurable speed/friction (?) + let movement = if state.keyboard_modifiers.shift() { + Vector::new(y, x) + } else { + Vector::new(x, y) + }; - state.scroll(delta, bounds, content_bounds); + movement * 60.0 + } + mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y), + }; - notify_on_scroll( - state, - on_scroll, - bounds, - content_bounds, - shell, - ); + state.scroll(delta, bounds, content_bounds); + + notify_on_scroll(state, on_scroll, bounds, content_bounds, shell); + + return event::Status::Captured; + } + Event::Touch(event) + if state.scroll_area_touched_at.is_some() + || !mouse_over_y_scrollbar && !mouse_over_x_scrollbar => + { + match event { + touch::Event::FingerPressed { .. } => { + state.scroll_area_touched_at = Some(cursor_position); + } + touch::Event::FingerMoved { .. } => { + if let Some(scroll_box_touched_at) = + state.scroll_area_touched_at + { + let delta = Vector::new( + cursor_position.x - scroll_box_touched_at.x, + cursor_position.y - scroll_box_touched_at.y, + ); + + state.scroll(delta, bounds, content_bounds); - return event::Status::Captured; - } - Event::Touch(event) - if state.scroll_area_touched_at.is_some() - || !mouse_over_y_scrollbar && !mouse_over_x_scrollbar => - { - match event { - touch::Event::FingerPressed { .. } => { state.scroll_area_touched_at = Some(cursor_position); - } - touch::Event::FingerMoved { .. } => { - if let Some(scroll_box_touched_at) = - state.scroll_area_touched_at - { - let delta = Vector::new( - cursor_position.x - scroll_box_touched_at.x, - cursor_position.y - scroll_box_touched_at.y, - ); - - state.scroll(delta, bounds, content_bounds); - - state.scroll_area_touched_at = - Some(cursor_position); - - notify_on_scroll( - state, - on_scroll, - bounds, - content_bounds, - shell, - ); - } - } - touch::Event::FingerLifted { .. } - | touch::Event::FingerLost { .. } => { - state.scroll_area_touched_at = None; + + notify_on_scroll( + state, + on_scroll, + bounds, + content_bounds, + shell, + ); } } - - return event::Status::Captured; + touch::Event::FingerLifted { .. } + | touch::Event::FingerLost { .. } => { + state.scroll_area_touched_at = None; + } } - _ => {} + + return event::Status::Captured; } + _ => {} } if let Some(scroller_grabbed_at) = state.y_scroller_grabbed_at { @@ -700,17 +688,17 @@ pub fn update<Message>( pub fn mouse_interaction( state: &State, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, vertical: &Properties, horizontal: Option<&Properties>, content_interaction: impl FnOnce( Layout<'_>, - Point, + mouse::Cursor, &Rectangle, ) -> mouse::Interaction, ) -> mouse::Interaction { let bounds = layout.bounds(); - let mouse_over_scrollable = bounds.contains(cursor_position); + let cursor_over_scrollable = cursor.position_over(&bounds); let content_layout = layout.children().next().unwrap(); let content_bounds = content_layout.bounds(); @@ -719,7 +707,7 @@ pub fn mouse_interaction( Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = - scrollbars.is_mouse_over(cursor_position); + scrollbars.is_mouse_over(cursor); if (mouse_over_x_scrollbar || mouse_over_y_scrollbar) || state.scrollers_grabbed() @@ -728,17 +716,18 @@ pub fn mouse_interaction( } else { let offset = state.offset(bounds, content_bounds); - let cursor_position = if mouse_over_scrollable - && !(mouse_over_y_scrollbar || mouse_over_x_scrollbar) - { - cursor_position + offset - } else { - Point::new(-1.0, -1.0) + let cursor = match cursor_over_scrollable { + Some(cursor_position) + if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => + { + mouse::Cursor::Available(cursor_position + offset) + } + _ => mouse::Cursor::Unavailable, }; content_interaction( content_layout, - cursor_position, + cursor, &Rectangle { y: bounds.y + offset.y, x: bounds.x + offset.x, @@ -754,11 +743,11 @@ pub fn draw<Renderer>( renderer: &mut Renderer, theme: &Renderer::Theme, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, vertical: &Properties, horizontal: Option<&Properties>, style: &<Renderer::Theme as StyleSheet>::Style, - draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle), + draw_content: impl FnOnce(&mut Renderer, Layout<'_>, mouse::Cursor, &Rectangle), ) where Renderer: crate::core::Renderer, Renderer::Theme: StyleSheet, @@ -770,18 +759,19 @@ pub fn draw<Renderer>( let scrollbars = Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); - let mouse_over_scrollable = bounds.contains(cursor_position); + let cursor_over_scrollable = cursor.position_over(&bounds); let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = - scrollbars.is_mouse_over(cursor_position); + scrollbars.is_mouse_over(cursor); let offset = state.offset(bounds, content_bounds); - let cursor_position = if mouse_over_scrollable - && !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) - { - cursor_position + offset - } else { - Point::new(-1.0, -1.0) + let cursor = match cursor_over_scrollable { + Some(cursor_position) + if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => + { + mouse::Cursor::Available(cursor_position + offset) + } + _ => mouse::Cursor::Unavailable, }; // Draw inner content @@ -793,7 +783,7 @@ pub fn draw<Renderer>( draw_content( renderer, content_layout, - cursor_position, + cursor, &Rectangle { y: bounds.y + offset.y, x: bounds.x + offset.x, @@ -858,7 +848,7 @@ pub fn draw<Renderer>( if let Some(scrollbar) = scrollbars.y { let style = if state.y_scroller_grabbed_at.is_some() { theme.dragging(style) - } else if mouse_over_scrollable { + } else if cursor_over_scrollable.is_some() { theme.hovered(style, mouse_over_y_scrollbar) } else { theme.active(style) @@ -871,7 +861,7 @@ pub fn draw<Renderer>( if let Some(scrollbar) = scrollbars.x { let style = if state.x_scroller_grabbed_at.is_some() { theme.dragging_horizontal(style) - } else if mouse_over_scrollable { + } else if cursor_over_scrollable.is_some() { theme.hovered_horizontal(style, mouse_over_x_scrollbar) } else { theme.active_horizontal(style) @@ -885,7 +875,7 @@ pub fn draw<Renderer>( draw_content( renderer, content_layout, - cursor_position, + cursor, &Rectangle { x: bounds.x + offset.x, y: bounds.y + offset.y, @@ -1283,17 +1273,21 @@ impl Scrollbars { } } - fn is_mouse_over(&self, cursor_position: Point) -> (bool, bool) { - ( - self.y - .as_ref() - .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) - .unwrap_or(false), - self.x - .as_ref() - .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) - .unwrap_or(false), - ) + fn is_mouse_over(&self, cursor: mouse::Cursor) -> (bool, bool) { + if let Some(cursor_position) = cursor.position() { + ( + self.y + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false), + self.x + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false), + ) + } else { + (false, false) + } } fn grab_y_scroller(&self, cursor_position: Point) -> Option<f32> { diff --git a/widget/src/slider.rs b/widget/src/slider.rs index c2498b87..4f35805c 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -183,7 +183,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -191,7 +191,7 @@ where update( event, layout, - cursor_position, + cursor, shell, tree.state.downcast_mut::<State>(), &mut self.value, @@ -209,13 +209,13 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { draw( renderer, layout, - cursor_position, + cursor, tree.state.downcast_ref::<State>(), self.value, &self.range, @@ -228,15 +228,11 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction( - layout, - cursor_position, - tree.state.downcast_ref::<State>(), - ) + mouse_interaction(layout, cursor, tree.state.downcast_ref::<State>()) } } @@ -260,7 +256,7 @@ where pub fn update<Message, T>( event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, state: &mut State, value: &mut T, @@ -275,7 +271,7 @@ where { let is_dragging = state.is_dragging; - let mut change = || { + let mut change = |cursor_position: Point| { let bounds = layout.bounds(); let new_value = if cursor_position.x <= bounds.x { *range.start() @@ -309,8 +305,10 @@ where match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if layout.bounds().contains(cursor_position) { - change(); + if let Some(cursor_position) = + cursor.position_over(&layout.bounds()) + { + change(cursor_position); state.is_dragging = true; return event::Status::Captured; @@ -331,7 +329,7 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - change(); + let _ = cursor.position().map(change); return event::Status::Captured; } @@ -346,7 +344,7 @@ where pub fn draw<T, R>( renderer: &mut R, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, state: &State, value: T, range: &RangeInclusive<T>, @@ -358,7 +356,7 @@ pub fn draw<T, R>( R::Theme: StyleSheet, { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); let style = if state.is_dragging { style_sheet.dragging(style) @@ -444,11 +442,11 @@ pub fn draw<T, R>( /// Computes the current [`mouse::Interaction`] of a [`Slider`]. pub fn mouse_interaction( layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, state: &State, ) -> mouse::Interaction { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); if state.is_dragging { mouse::Interaction::Grabbing diff --git a/widget/src/space.rs b/widget/src/space.rs index e1e09d5a..9a5385e8 100644 --- a/widget/src/space.rs +++ b/widget/src/space.rs @@ -1,9 +1,10 @@ //! Distribute content vertically. use crate::core; use crate::core::layout; +use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{Element, Layout, Length, Point, Rectangle, Size, Widget}; +use crate::core::{Element, Layout, Length, Rectangle, Size, Widget}; /// An amount of empty space. /// @@ -69,7 +70,7 @@ where _theme: &Renderer::Theme, _style: &renderer::Style, _layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { } diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 89017fcf..1ccc5d62 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -1,10 +1,11 @@ //! Display vector graphics in your application. use crate::core::layout; +use crate::core::mouse; use crate::core::renderer; use crate::core::svg; use crate::core::widget::Tree; use crate::core::{ - ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget, + ContentFit, Element, Layout, Length, Rectangle, Size, Vector, Widget, }; use std::path::PathBuf; @@ -143,7 +144,7 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { let Size { width, height } = renderer.dimensions(&self.handle); diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 8f243c1a..5b3705d4 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -207,14 +207,14 @@ where renderer: &mut Renderer, theme: &Renderer::Theme, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, value: Option<&Value>, ) { draw( renderer, theme, layout, - cursor_position, + cursor, tree.state.downcast_ref::<State>(), value.unwrap_or(&self.value), &self.placeholder, @@ -298,7 +298,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -306,7 +306,7 @@ where update( event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -329,14 +329,14 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { draw( renderer, theme, layout, - cursor_position, + cursor, tree.state.downcast_ref::<State>(), &self.value, &self.placeholder, @@ -354,11 +354,11 @@ where &self, _state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction(layout, cursor_position, self.on_input.is_none()) + mouse_interaction(layout, cursor, self.on_input.is_none()) } } @@ -528,7 +528,7 @@ where pub fn update<'a, Message, Renderer>( event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -550,10 +550,14 @@ where Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let state = state(); - let is_clicked = - layout.bounds().contains(cursor_position) && on_input.is_some(); - state.is_focused = if is_clicked { + let click_position = if on_input.is_some() { + cursor.position_over(&layout.bounds()) + } else { + None + }; + + state.is_focused = if click_position.is_some() { state.is_focused.or_else(|| { let now = Instant::now(); @@ -566,7 +570,7 @@ where None }; - if is_clicked { + if let Some(cursor_position) = click_position { let text_layout = layout.children().next().unwrap(); let target = cursor_position.x - text_layout.bounds().x; @@ -944,7 +948,7 @@ pub fn draw<Renderer>( renderer: &mut Renderer, theme: &Renderer::Theme, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, state: &State, value: &Value, placeholder: &str, @@ -967,7 +971,7 @@ pub fn draw<Renderer>( let mut children_layout = layout.children(); let text_bounds = children_layout.next().unwrap().bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&bounds); let appearance = if is_disabled { theme.disabled(style) @@ -1154,10 +1158,10 @@ pub fn draw<Renderer>( /// Computes the current [`mouse::Interaction`] of the [`TextInput`]. pub fn mouse_interaction( layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, is_disabled: bool, ) -> mouse::Interaction { - if layout.bounds().contains(cursor_position) { + if cursor.is_over(&layout.bounds()) { if is_disabled { mouse::Interaction::NotAllowed } else { diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index b1ba65c9..28715c5a 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -7,8 +7,8 @@ use crate::core::renderer; use crate::core::text; use crate::core::widget::Tree; use crate::core::{ - Alignment, Clipboard, Element, Event, Layout, Length, Pixels, Point, - Rectangle, Shell, Widget, + Alignment, Clipboard, Element, Event, Layout, Length, Pixels, Rectangle, + Shell, Widget, }; use crate::{Row, Text}; @@ -202,14 +202,14 @@ where _state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { - let mouse_over = layout.bounds().contains(cursor_position); + let mouse_over = cursor.is_over(&layout.bounds()); if mouse_over { shell.publish((self.on_toggle)(!self.is_toggled)); @@ -227,11 +227,11 @@ where &self, _state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - if layout.bounds().contains(cursor_position) { + if cursor.is_over(&layout.bounds()) { mouse::Interaction::Pointer } else { mouse::Interaction::default() @@ -245,7 +245,7 @@ where theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { /// Makes sure that the border radius of the toggler looks good at every size. @@ -278,7 +278,7 @@ where let toggler_layout = children.next().unwrap(); let bounds = toggler_layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.is_over(&layout.bounds()); let style = if is_mouse_over { theme.hovered(&self.style, self.is_toggled) diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs index 084650d1..024cfa9c 100644 --- a/widget/src/tooltip.rs +++ b/widget/src/tooltip.rs @@ -9,7 +9,7 @@ use crate::core::renderer; use crate::core::text; use crate::core::widget::Tree; use crate::core::{ - Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, Shell, Size, + Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, }; use crate::Text; @@ -136,7 +136,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -145,7 +145,7 @@ where &mut tree.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -156,14 +156,14 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &tree.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -176,7 +176,7 @@ where theme: &Renderer::Theme, inherited_style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( @@ -185,7 +185,7 @@ where theme, inherited_style, layout, - cursor_position, + cursor, viewport, ); @@ -196,7 +196,7 @@ where theme, inherited_style, layout, - cursor_position, + cursor, viewport, self.position, self.gap, @@ -206,7 +206,7 @@ where |renderer, limits| { Widget::<(), Renderer>::layout(tooltip, renderer, limits) }, - |renderer, defaults, layout, cursor_position, viewport| { + |renderer, defaults, layout, viewport| { Widget::<(), Renderer>::draw( tooltip, &Tree::empty(), @@ -214,7 +214,7 @@ where theme, defaults, layout, - cursor_position, + cursor, viewport, ); }, @@ -270,7 +270,7 @@ pub fn draw<Renderer>( theme: &Renderer::Theme, inherited_style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, position: Position, gap: f32, @@ -278,13 +278,7 @@ pub fn draw<Renderer>( snap_within_viewport: bool, style: &<Renderer::Theme as container::StyleSheet>::Style, layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node, - draw_text: impl FnOnce( - &mut Renderer, - &renderer::Style, - Layout<'_>, - Point, - &Rectangle, - ), + draw_text: impl FnOnce(&mut Renderer, &renderer::Style, Layout<'_>, &Rectangle), ) where Renderer: core::Renderer, Renderer::Theme: container::StyleSheet, @@ -293,7 +287,7 @@ pub fn draw<Renderer>( let bounds = layout.bounds(); - if bounds.contains(cursor_position) { + if let Some(cursor_position) = cursor.position_over(&bounds) { let style = theme.appearance(style); let defaults = renderer::Style { @@ -380,7 +374,6 @@ pub fn draw<Renderer>( ), &text_layout, ), - cursor_position, viewport, ) }); diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index b14e5401..47b14d57 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -180,7 +180,7 @@ where tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -188,7 +188,7 @@ where update( event, layout, - cursor_position, + cursor, shell, tree.state.downcast_mut::<State>(), &mut self.value, @@ -206,13 +206,13 @@ where theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { draw( renderer, layout, - cursor_position, + cursor, tree.state.downcast_ref::<State>(), self.value, &self.range, @@ -225,15 +225,11 @@ where &self, tree: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction( - layout, - cursor_position, - tree.state.downcast_ref::<State>(), - ) + mouse_interaction(layout, cursor, tree.state.downcast_ref::<State>()) } } @@ -257,7 +253,7 @@ where pub fn update<Message, T>( event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, state: &mut State, value: &mut T, @@ -272,8 +268,9 @@ where { let is_dragging = state.is_dragging; - let mut change = || { + let mut change = |cursor_position: Point| { let bounds = layout.bounds(); + let new_value = if cursor_position.y >= bounds.y + bounds.height { *range.start() } else if cursor_position.y <= bounds.y { @@ -307,8 +304,10 @@ where match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if layout.bounds().contains(cursor_position) { - change(); + if let Some(cursor_position) = + cursor.position_over(&layout.bounds()) + { + change(cursor_position); state.is_dragging = true; return event::Status::Captured; @@ -329,7 +328,7 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - change(); + let _ = cursor.position().map(change); return event::Status::Captured; } @@ -344,7 +343,7 @@ where pub fn draw<T, R>( renderer: &mut R, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, state: &State, value: T, range: &RangeInclusive<T>, @@ -356,7 +355,7 @@ pub fn draw<T, R>( R::Theme: StyleSheet, { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.position_over(&bounds).is_some(); let style = if state.is_dragging { style_sheet.dragging(style) @@ -442,11 +441,11 @@ pub fn draw<T, R>( /// Computes the current [`mouse::Interaction`] of a [`VerticalSlider`]. pub fn mouse_interaction( layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, state: &State, ) -> mouse::Interaction { let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); + let is_mouse_over = cursor.position_over(&bounds).is_some(); if state.is_dragging { mouse::Interaction::Grabbing |