Implement basic cursor availability

This commit is contained in:
Héctor Ramón Jiménez 2023-06-08 20:11:59 +02:00
parent c15f1b5f65
commit 34451bff18
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
55 changed files with 731 additions and 886 deletions

View file

@ -5,9 +5,7 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::widget; use crate::widget;
use crate::widget::tree::{self, Tree}; use crate::widget::tree::{self, Tree};
use crate::{ use crate::{Clipboard, Color, Layout, Length, Rectangle, Shell, Widget};
Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Widget,
};
use std::any::Any; use std::any::Any;
use std::borrow::Borrow; use std::borrow::Borrow;
@ -378,7 +376,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, B>, shell: &mut Shell<'_, B>,
@ -390,7 +388,7 @@ where
tree, tree,
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,
@ -408,35 +406,23 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.widget.draw( self.widget
tree, .draw(tree, renderer, theme, style, layout, cursor, viewport)
renderer,
theme,
style,
layout,
cursor_position,
viewport,
)
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.widget.mouse_interaction( self.widget
tree, .mouse_interaction(tree, layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
} }
fn overlay<'b>( fn overlay<'b>(
@ -521,20 +507,14 @@ where
state: &mut Tree, state: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.element.widget.on_event( self.element
state, .widget
event, .on_event(state, event, layout, cursor, renderer, clipboard, shell)
layout,
cursor_position,
renderer,
clipboard,
shell,
)
} }
fn draw( fn draw(
@ -544,7 +524,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
fn explain_layout<Renderer: crate::Renderer>( fn explain_layout<Renderer: crate::Renderer>(
@ -567,15 +547,9 @@ where
} }
} }
self.element.widget.draw( self.element
state, .widget
renderer, .draw(state, renderer, theme, style, layout, cursor, viewport);
theme,
style,
layout,
cursor_position,
viewport,
);
explain_layout(renderer, self.color, layout); explain_layout(renderer, self.color, layout);
} }
@ -584,17 +558,13 @@ where
&self, &self,
state: &Tree, state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.element.widget.mouse_interaction( self.element
state, .widget
layout, .mouse_interaction(state, layout, cursor, viewport, renderer)
cursor_position,
viewport,
renderer,
)
} }
fn overlay<'b>( fn overlay<'b>(

View file

@ -2,10 +2,12 @@
pub mod click; pub mod click;
mod button; mod button;
mod cursor;
mod event; mod event;
mod interaction; mod interaction;
pub use button::Button; pub use button::Button;
pub use click::Click; pub use click::Click;
pub use cursor::Cursor;
pub use event::{Event, ScrollDelta}; pub use event::{Event, ScrollDelta};
pub use interaction::Interaction; pub use interaction::Interaction;

51
core/src/mouse/cursor.rs Normal file
View file

@ -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()
}
}

View file

@ -38,7 +38,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
); );
/// Applies a [`widget::Operation`] to the [`Overlay`]. /// Applies a [`widget::Operation`] to the [`Overlay`].
@ -66,7 +66,7 @@ where
&mut self, &mut self,
_event: Event, _event: Event,
_layout: Layout<'_>, _layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_shell: &mut Shell<'_, Message>, _shell: &mut Shell<'_, Message>,
@ -80,7 +80,7 @@ where
fn mouse_interaction( fn mouse_interaction(
&self, &self,
_layout: Layout<'_>, _layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {

View file

@ -68,35 +68,25 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.overlay.on_event( self.overlay
event, .on_event(event, layout, cursor, renderer, clipboard, shell)
layout,
cursor_position,
renderer,
clipboard,
shell,
)
} }
/// Returns the current [`mouse::Interaction`] of the [`Element`]. /// Returns the current [`mouse::Interaction`] of the [`Element`].
pub fn mouse_interaction( pub fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.overlay.mouse_interaction( self.overlay
layout, .mouse_interaction(layout, cursor, viewport, renderer)
cursor_position,
viewport,
renderer,
)
} }
/// Draws the [`Element`] and its children using the given [`Layout`]. /// Draws the [`Element`] and its children using the given [`Layout`].
@ -106,10 +96,9 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
self.overlay self.overlay.draw(renderer, theme, style, layout, cursor)
.draw(renderer, theme, style, layout, cursor_position)
} }
/// Applies a [`widget::Operation`] to the [`Element`]. /// Applies a [`widget::Operation`] to the [`Element`].
@ -215,7 +204,7 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, B>, shell: &mut Shell<'_, B>,
@ -226,7 +215,7 @@ where
let event_status = self.content.on_event( let event_status = self.content.on_event(
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,
@ -240,16 +229,12 @@ where
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.mouse_interaction( self.content
layout, .mouse_interaction(layout, cursor, viewport, renderer)
cursor_position,
viewport,
renderer,
)
} }
fn draw( fn draw(
@ -258,10 +243,9 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
self.content self.content.draw(renderer, theme, style, layout, cursor)
.draw(renderer, theme, style, layout, cursor_position)
} }
fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool { fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {

View file

@ -81,7 +81,7 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -93,7 +93,7 @@ where
child.on_event( child.on_event(
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -108,17 +108,17 @@ where
theme: &<Renderer as crate::Renderer>::Theme, theme: &<Renderer as crate::Renderer>::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
for (child, layout) in self.children.iter().zip(layout.children()) { 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( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -126,12 +126,7 @@ where
.iter() .iter()
.zip(layout.children()) .zip(layout.children())
.map(|(child, layout)| { .map(|(child, layout)| {
child.mouse_interaction( child.mouse_interaction(layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
}) })
.max() .max()
.unwrap_or_default() .unwrap_or_default()

View file

@ -15,7 +15,7 @@ use crate::layout::{self, Layout};
use crate::mouse; use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{Clipboard, Length, Point, Rectangle, Shell}; use crate::{Clipboard, Length, Rectangle, Shell};
/// A component that displays information and allows interaction. /// A component that displays information and allows interaction.
/// ///
@ -67,7 +67,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
); );
@ -111,7 +111,7 @@ where
_state: &mut Tree, _state: &mut Tree,
_event: Event, _event: Event,
_layout: Layout<'_>, _layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_shell: &mut Shell<'_, Message>, _shell: &mut Shell<'_, Message>,
@ -126,7 +126,7 @@ where
&self, &self,
_state: &Tree, _state: &Tree,
_layout: Layout<'_>, _layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {

View file

@ -1,12 +1,11 @@
//! Write some text for your users to read. //! Write some text for your users to read.
use crate::alignment; use crate::alignment;
use crate::layout; use crate::layout;
use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::text; use crate::text;
use crate::widget::Tree; use crate::widget::Tree;
use crate::{ use crate::{Color, Element, Layout, Length, Pixels, Rectangle, Size, Widget};
Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget,
};
use std::borrow::Cow; use std::borrow::Cow;
@ -163,7 +162,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor_position: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw( draw(

View file

@ -1,8 +1,9 @@
use std::{f32::consts::PI, time::Instant}; use std::{f32::consts::PI, time::Instant};
use iced::executor; use iced::executor;
use iced::mouse;
use iced::widget::canvas::{ use iced::widget::canvas::{
self, stroke, Cache, Canvas, Cursor, Geometry, Path, Stroke, self, stroke, Cache, Canvas, Geometry, Path, Stroke,
}; };
use iced::{ use iced::{
Application, Command, Element, Length, Point, Rectangle, Renderer, Application, Command, Element, Length, Point, Rectangle, Renderer,
@ -78,7 +79,7 @@ impl<Message> canvas::Program<Message> for Arc {
renderer: &Renderer, renderer: &Renderer,
theme: &Theme, theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let geometry = self.cache.draw(renderer, bounds.size(), |frame| {
let palette = theme.palette(); let palette = theme.palette();

View file

@ -61,9 +61,7 @@ impl Sandbox for Example {
mod bezier { mod bezier {
use iced::mouse; use iced::mouse;
use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::event::{self, Event};
use iced::widget::canvas::{ use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke};
self, Canvas, Cursor, Frame, Geometry, Path, Stroke,
};
use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; use iced::{Element, Length, Point, Rectangle, Renderer, Theme};
#[derive(Default)] #[derive(Default)]
@ -100,7 +98,7 @@ mod bezier {
state: &mut Self::State, state: &mut Self::State,
event: Event, event: Event,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> (event::Status, Option<Curve>) { ) -> (event::Status, Option<Curve>) {
let cursor_position = let cursor_position =
if let Some(position) = cursor.position_in(&bounds) { if let Some(position) = cursor.position_in(&bounds) {
@ -155,7 +153,7 @@ mod bezier {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let content = self.state.cache.draw( let content = self.state.cache.draw(
renderer, renderer,
@ -183,7 +181,7 @@ mod bezier {
&self, &self,
_state: &Self::State, _state: &Self::State,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
if cursor.is_over(&bounds) { if cursor.is_over(&bounds) {
mouse::Interaction::Crosshair mouse::Interaction::Crosshair
@ -224,7 +222,7 @@ mod bezier {
&self, &self,
renderer: &Renderer, renderer: &Renderer,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> Geometry { ) -> Geometry {
let mut frame = Frame::new(renderer, bounds.size()); let mut frame = Frame::new(renderer, bounds.size());

View file

@ -1,7 +1,6 @@
use iced::executor; use iced::executor;
use iced::widget::canvas::{ use iced::mouse;
stroke, Cache, Cursor, Geometry, LineCap, Path, Stroke, use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke};
};
use iced::widget::{canvas, container}; use iced::widget::{canvas, container};
use iced::{ use iced::{
Application, Color, Command, Element, Length, Point, Rectangle, Renderer, Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
@ -92,7 +91,7 @@ impl<Message> canvas::Program<Message, Renderer> for Clock {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let clock = self.clock.draw(renderer, bounds.size(), |frame| { let clock = self.clock.draw(renderer, bounds.size(), |frame| {
let center = frame.center(); let center = frame.center();

View file

@ -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::widget::{column, row, text, Slider};
use iced::{ use iced::{
alignment, Alignment, Color, Element, Length, Point, Rectangle, Renderer, Color, Element, Length, Point, Rectangle, Renderer, Sandbox, Settings,
Sandbox, Settings, Size, Vector, Size, Vector,
}; };
use palette::{ use palette::{
self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue, self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue,
@ -246,7 +248,7 @@ impl<Message> canvas::Program<Message> for Theme {
renderer: &Renderer, renderer: &Renderer,
_theme: &iced::Theme, _theme: &iced::Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| { let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| {
self.draw(frame); self.draw(frame);

View file

@ -3,7 +3,8 @@ mod quad {
use iced::advanced::layout::{self, Layout}; use iced::advanced::layout::{self, Layout};
use iced::advanced::renderer; use iced::advanced::renderer;
use iced::advanced::widget::{self, Widget}; 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 { pub struct CustomQuad {
size: f32, size: f32,
@ -48,7 +49,7 @@ mod quad {
_theme: &Renderer::Theme, _theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
renderer.fill_quad( renderer.fill_quad(

View file

@ -12,7 +12,8 @@ mod circle {
use iced::advanced::layout::{self, Layout}; use iced::advanced::layout::{self, Layout};
use iced::advanced::renderer; use iced::advanced::renderer;
use iced::advanced::widget::{self, Widget}; 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 { pub struct Circle {
radius: f32, radius: f32,
@ -55,7 +56,7 @@ mod circle {
_theme: &Renderer::Theme, _theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
renderer.fill_quad( renderer.fill_quad(

View file

@ -204,15 +204,14 @@ fn view_controls<'a>(
mod grid { mod grid {
use crate::Preset; use crate::Preset;
use iced::alignment;
use iced::mouse;
use iced::touch; use iced::touch;
use iced::widget::canvas; use iced::widget::canvas;
use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::event::{self, Event};
use iced::widget::canvas::{ use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text};
Cache, Canvas, Cursor, Frame, Geometry, Path, Text,
};
use iced::{ use iced::{
alignment, mouse, Color, Element, Length, Point, Rectangle, Renderer, Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector,
Size, Theme, Vector,
}; };
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::future::Future; use std::future::Future;
@ -401,7 +400,7 @@ mod grid {
interaction: &mut Interaction, interaction: &mut Interaction,
event: Event, event: Event,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> (event::Status, Option<Message>) { ) -> (event::Status, Option<Message>) {
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event { if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
*interaction = Interaction::None; *interaction = Interaction::None;
@ -539,7 +538,7 @@ mod grid {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0); let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0);
@ -670,7 +669,7 @@ mod grid {
&self, &self,
interaction: &Interaction, interaction: &Interaction,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
match interaction { match interaction {
Interaction::Drawing => mouse::Interaction::Crosshair, Interaction::Drawing => mouse::Interaction::Crosshair,

View file

@ -7,9 +7,8 @@ mod rainbow {
use iced::advanced::layout::{self, Layout}; use iced::advanced::layout::{self, Layout};
use iced::advanced::renderer; use iced::advanced::renderer;
use iced::advanced::widget::{self, Widget}; use iced::advanced::widget::{self, Widget};
use iced::{ use iced::mouse;
Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, use iced::{Element, Length, Rectangle, Renderer, Size, Theme, Vector};
};
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Rainbow; pub struct Rainbow;
@ -44,13 +43,13 @@ mod rainbow {
_theme: &Theme, _theme: &Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
use iced::advanced::Renderer as _; use iced::advanced::Renderer as _;
use iced_graphics::primitive::Mesh2D; use iced_graphics::primitive::Mesh2D;
let b = layout.bounds(); let bounds = layout.bounds();
// R O Y G B I V // R O Y G B I V
let color_r = [1.0, 0.0, 0.0, 1.0]; 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 color_v = [0.75, 0.0, 0.5, 1.0];
let posn_center = { let posn_center = {
if b.contains(cursor_position) { if let Some(cursor_position) = cursor.position_in(&bounds) {
[cursor_position.x - b.x, cursor_position.y - b.y] [cursor_position.x, cursor_position.y]
} else { } 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_tl = [0.0, 0.0];
let posn_t = [b.width / 2.0, 0.0]; let posn_t = [bounds.width / 2.0, 0.0];
let posn_tr = [b.width, 0.0]; let posn_tr = [bounds.width, 0.0];
let posn_r = [b.width, b.height / 2.0]; let posn_r = [bounds.width, bounds.height / 2.0];
let posn_br = [b.width, b.height]; let posn_br = [bounds.width, bounds.height];
let posn_b = [(b.width / 2.0), b.height]; let posn_b = [(bounds.width / 2.0), bounds.height];
let posn_bl = [0.0, b.height]; let posn_bl = [0.0, bounds.height];
let posn_l = [0.0, b.height / 2.0]; let posn_l = [0.0, bounds.height / 2.0];
let mesh = Primitive::SolidMesh { let mesh = Primitive::SolidMesh {
size: b.size(), size: bounds.size(),
buffers: Mesh2D { buffers: Mesh2D {
vertices: vec![ vertices: vec![
ColoredVertex2D { ColoredVertex2D {
@ -133,9 +132,12 @@ mod rainbow {
}, },
}; };
renderer.with_translation(Vector::new(b.x, b.y), |renderer| { renderer.with_translation(
renderer.draw_primitive(mesh); Vector::new(bounds.x, bounds.y),
}); |renderer| {
renderer.draw_primitive(mesh);
},
);
} }
} }

View file

@ -1,10 +1,11 @@
use iced::executor;
use iced::keyboard;
use iced::subscription::{self, Subscription};
use iced::theme;
use iced::widget::{ use iced::widget::{
self, button, column, container, horizontal_space, row, text, text_input, self, button, column, container, horizontal_space, row, text, text_input,
}; };
use iced::{ use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
executor, keyboard, subscription, theme, Alignment, Application, Command,
Element, Event, Length, Settings, Subscription,
};
use self::modal::Modal; use self::modal::Modal;
@ -254,7 +255,7 @@ mod modal {
state: &mut widget::Tree, state: &mut widget::Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -263,7 +264,7 @@ mod modal {
&mut state.children[0], &mut state.children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -277,7 +278,7 @@ mod modal {
theme: &<Renderer as advanced::Renderer>::Theme, theme: &<Renderer as advanced::Renderer>::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.base.as_widget().draw( self.base.as_widget().draw(
@ -286,7 +287,7 @@ mod modal {
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -312,14 +313,14 @@ mod modal {
&self, &self,
state: &widget::Tree, state: &widget::Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.base.as_widget().mouse_interaction( self.base.as_widget().mouse_interaction(
&state.children[0], &state.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -377,7 +378,7 @@ mod modal {
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -389,7 +390,7 @@ mod modal {
mouse::Button::Left, mouse::Button::Left,
)) = &event )) = &event
{ {
if !content_bounds.contains(cursor_position) { if !cursor.is_over(&content_bounds) {
shell.publish(message.clone()); shell.publish(message.clone());
return event::Status::Captured; return event::Status::Captured;
} }
@ -400,7 +401,7 @@ mod modal {
self.tree, self.tree,
event, event,
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -413,7 +414,7 @@ mod modal {
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
renderer.fill_quad( renderer.fill_quad(
renderer::Quad { renderer::Quad {
@ -434,7 +435,7 @@ mod modal {
theme, theme,
style, style,
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
&layout.bounds(), &layout.bounds(),
); );
} }
@ -456,14 +457,14 @@ mod modal {
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
self.tree, self.tree,
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )

View file

@ -1,9 +1,10 @@
//! This example shows how to use touch events in `Canvas` to draw //! This example shows how to use touch events in `Canvas` to draw
//! a circle around each fingertip. This only works on touch-enabled //! a circle around each fingertip. This only works on touch-enabled
//! computers like Microsoft Surface. //! computers like Microsoft Surface.
use iced::mouse;
use iced::widget::canvas::event; use iced::widget::canvas::event;
use iced::widget::canvas::stroke::{self, Stroke}; use iced::widget::canvas::stroke::{self, Stroke};
use iced::widget::canvas::{self, Canvas, Cursor, Geometry}; use iced::widget::canvas::{self, Canvas, Geometry};
use iced::{ use iced::{
executor, touch, window, Application, Color, Command, Element, Length, executor, touch, window, Application, Color, Command, Element, Length,
Point, Rectangle, Renderer, Settings, Subscription, Theme, Point, Rectangle, Renderer, Settings, Subscription, Theme,
@ -103,7 +104,7 @@ impl canvas::Program<Message, Renderer> for State {
_state: &mut Self::State, _state: &mut Self::State,
event: event::Event, event: event::Event,
_bounds: Rectangle, _bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> (event::Status, Option<Message>) { ) -> (event::Status, Option<Message>) {
match event { match event {
event::Event::Touch(touch_event) => match touch_event { event::Event::Touch(touch_event) => match touch_event {
@ -128,7 +129,7 @@ impl canvas::Program<Message, Renderer> for State {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| {
if self.fingers.len() < 2 { if self.fingers.len() < 2 {

View file

@ -1,6 +1,7 @@
use std::fmt::Debug; use std::fmt::Debug;
use iced::executor; use iced::executor;
use iced::mouse;
use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::event::{self, Event};
use iced::widget::canvas::{self, Canvas}; use iced::widget::canvas::{self, Canvas};
use iced::widget::{column, row, slider, text}; use iced::widget::{column, row, slider, text};
@ -105,7 +106,7 @@ impl canvas::Program<Message> for SierpinskiGraph {
_state: &mut Self::State, _state: &mut Self::State,
event: Event, event: Event,
bounds: Rectangle, bounds: Rectangle,
cursor: canvas::Cursor, cursor: mouse::Cursor,
) -> (event::Status, Option<Message>) { ) -> (event::Status, Option<Message>) {
let cursor_position = let cursor_position =
if let Some(position) = cursor.position_in(&bounds) { if let Some(position) = cursor.position_in(&bounds) {
@ -137,7 +138,7 @@ impl canvas::Program<Message> for SierpinskiGraph {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: canvas::Cursor, _cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> { ) -> Vec<canvas::Geometry> {
let geom = self.cache.draw(renderer, bounds.size(), |frame| { let geom = self.cache.draw(renderer, bounds.size(), |frame| {
frame.stroke( frame.stroke(

View file

@ -8,11 +8,12 @@
//! [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations#An_animated_solar_system //! [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations#An_animated_solar_system
use iced::application; use iced::application;
use iced::executor; use iced::executor;
use iced::mouse;
use iced::theme::{self, Theme}; use iced::theme::{self, Theme};
use iced::widget::canvas; use iced::widget::canvas;
use iced::widget::canvas::gradient; use iced::widget::canvas::gradient;
use iced::widget::canvas::stroke::{self, Stroke}; use iced::widget::canvas::stroke::{self, Stroke};
use iced::widget::canvas::{Cursor, Path}; use iced::widget::canvas::Path;
use iced::window; use iced::window;
use iced::{ use iced::{
Application, Color, Command, Element, Length, Point, Rectangle, Renderer, Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
@ -161,7 +162,7 @@ impl<Message> canvas::Program<Message> for State {
renderer: &Renderer, renderer: &Renderer,
_theme: &Theme, _theme: &Theme,
bounds: Rectangle, bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> { ) -> Vec<canvas::Geometry> {
use std::f32::consts::PI; use std::f32::consts::PI;

View file

@ -1,10 +1,10 @@
use iced::executor;
use iced::keyboard;
use iced::subscription::{self, Subscription};
use iced::widget::{ use iced::widget::{
self, button, column, container, pick_list, row, slider, text, text_input, self, button, column, container, pick_list, row, slider, text, text_input,
}; };
use iced::{ use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
executor, keyboard, subscription, Alignment, Application, Command, Element,
Event, Length, Settings, Subscription,
};
use toast::{Status, Toast}; use toast::{Status, Toast};
@ -396,7 +396,7 @@ mod toast {
state: &mut Tree, state: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -405,7 +405,7 @@ mod toast {
&mut state.children[0], &mut state.children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -419,7 +419,7 @@ mod toast {
theme: &Theme, theme: &Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.content.as_widget().draw( self.content.as_widget().draw(
@ -428,7 +428,7 @@ mod toast {
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -437,14 +437,14 @@ mod toast {
&self, &self,
state: &Tree, state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&state.children[0], &state.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -523,7 +523,7 @@ mod toast {
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -572,7 +572,7 @@ mod toast {
state, state,
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,
@ -595,7 +595,7 @@ mod toast {
theme: &<Renderer as advanced::Renderer>::Theme, theme: &<Renderer as advanced::Renderer>::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
let viewport = layout.bounds(); let viewport = layout.bounds();
@ -606,13 +606,7 @@ mod toast {
.zip(layout.children()) .zip(layout.children())
{ {
child.as_widget().draw( child.as_widget().draw(
state, state, renderer, theme, style, layout, cursor, &viewport,
renderer,
theme,
style,
layout,
cursor_position,
&viewport,
); );
} }
} }
@ -639,7 +633,7 @@ mod toast {
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -649,11 +643,7 @@ mod toast {
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), layout)| {
child.as_widget().mouse_interaction( child.as_widget().mouse_interaction(
state, state, layout, cursor, viewport, renderer,
layout,
cursor_position,
viewport,
renderer,
) )
}) })
.max() .max()

View file

@ -203,7 +203,7 @@ where
let event_status = overlay.on_event( let event_status = overlay.on_event(
event, event,
Layout::new(&layout), Layout::new(&layout),
cursor_position, mouse::Cursor::Available(cursor_position),
renderer, renderer,
clipboard, clipboard,
&mut shell, &mut shell,
@ -257,17 +257,17 @@ where
.filter(|overlay| { .filter(|overlay| {
overlay.is_over(Layout::new(&layout), cursor_position) overlay.is_over(Layout::new(&layout), cursor_position)
}) })
.map(|_| { .map(|_| mouse::Cursor::Unavailable)
// TODO: Type-safe cursor availability .unwrap_or(mouse::Cursor::Available(cursor_position));
Point::new(-1.0, -1.0)
})
.unwrap_or(cursor_position);
self.overlay = Some(layout); self.overlay = Some(layout);
(base_cursor, event_statuses) (base_cursor, event_statuses)
} else { } 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); let _ = ManuallyDrop::into_inner(manual_overlay);
@ -427,19 +427,19 @@ where
overlay.layout(renderer, self.bounds, Vector::ZERO) 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) .is_over(Layout::new(&overlay_layout), cursor_position)
{ {
Point::new(-1.0, -1.0) mouse::Cursor::Unavailable
} else { } else {
cursor_position mouse::Cursor::Available(cursor_position)
}; };
self.overlay = Some(overlay_layout); self.overlay = Some(overlay_layout);
new_cursor_position cursor
} else { } else {
cursor_position mouse::Cursor::Available(cursor_position)
}; };
self.root.as_widget().draw( self.root.as_widget().draw(
@ -455,7 +455,7 @@ where
let base_interaction = self.root.as_widget().mouse_interaction( let base_interaction = self.root.as_widget().mouse_interaction(
&self.state, &self.state,
Layout::new(&self.base), Layout::new(&self.base),
cursor_position, base_cursor,
&viewport, &viewport,
renderer, renderer,
); );
@ -480,7 +480,7 @@ where
.map(|overlay| { .map(|overlay| {
let overlay_interaction = overlay.mouse_interaction( let overlay_interaction = overlay.mouse_interaction(
Layout::new(layout), Layout::new(layout),
cursor_position, mouse::Cursor::Available(cursor_position),
&viewport, &viewport,
renderer, renderer,
); );
@ -493,7 +493,7 @@ where
theme, theme,
style, style,
Layout::new(layout), Layout::new(layout),
cursor_position, mouse::Cursor::Available(cursor_position),
); );
}); });

View file

@ -230,7 +230,9 @@ pub mod keyboard {
pub mod mouse { pub mod mouse {
//! Listen and react to mouse events. //! 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 { pub mod subscription {

View file

@ -187,7 +187,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -196,7 +196,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -204,14 +204,9 @@ where
return event::Status::Captured; return event::Status::Captured;
} }
update( update(event, layout, cursor, shell, &self.on_press, || {
event, tree.state.downcast_mut::<State>()
layout, })
cursor_position,
shell,
&self.on_press,
|| tree.state.downcast_mut::<State>(),
)
} }
fn draw( fn draw(
@ -221,7 +216,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let bounds = layout.bounds();
@ -230,7 +225,7 @@ where
let styling = draw( let styling = draw(
renderer, renderer,
bounds, bounds,
cursor_position, cursor,
self.on_press.is_some(), self.on_press.is_some(),
theme, theme,
&self.style, &self.style,
@ -245,7 +240,7 @@ where
text_color: styling.text_color, text_color: styling.text_color,
}, },
content_layout, content_layout,
cursor_position, cursor,
&bounds, &bounds,
); );
} }
@ -254,11 +249,11 @@ where
&self, &self,
_tree: &Tree, _tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction(layout, cursor_position, self.on_press.is_some()) mouse_interaction(layout, cursor, self.on_press.is_some())
} }
fn overlay<'b>( fn overlay<'b>(
@ -305,7 +300,7 @@ impl State {
pub fn update<'a, Message: Clone>( pub fn update<'a, Message: Clone>(
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
on_press: &Option<Message>, on_press: &Option<Message>,
state: impl FnOnce() -> &'a mut State, state: impl FnOnce() -> &'a mut State,
@ -316,7 +311,7 @@ pub fn update<'a, Message: Clone>(
if on_press.is_some() { if on_press.is_some() {
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if cursor.is_over(&bounds) {
let state = state(); let state = state();
state.is_pressed = true; state.is_pressed = true;
@ -335,7 +330,7 @@ pub fn update<'a, Message: Clone>(
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if cursor.is_over(&bounds) {
shell.publish(on_press); shell.publish(on_press);
} }
@ -358,7 +353,7 @@ pub fn update<'a, Message: Clone>(
pub fn draw<'a, Renderer: crate::core::Renderer>( pub fn draw<'a, Renderer: crate::core::Renderer>(
renderer: &mut Renderer, renderer: &mut Renderer,
bounds: Rectangle, bounds: Rectangle,
cursor_position: Point, cursor: mouse::Cursor,
is_enabled: bool, is_enabled: bool,
style_sheet: &dyn StyleSheet< style_sheet: &dyn StyleSheet<
Style = <Renderer::Theme as StyleSheet>::Style, Style = <Renderer::Theme as StyleSheet>::Style,
@ -369,7 +364,7 @@ pub fn draw<'a, Renderer: crate::core::Renderer>(
where where
Renderer::Theme: StyleSheet, Renderer::Theme: StyleSheet,
{ {
let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over = cursor.is_over(&bounds);
let styling = if !is_enabled { let styling = if !is_enabled {
style_sheet.disabled(style) style_sheet.disabled(style)
@ -442,10 +437,10 @@ pub fn layout<Renderer>(
/// Returns the [`mouse::Interaction`] of a [`Button`]. /// Returns the [`mouse::Interaction`] of a [`Button`].
pub fn mouse_interaction( pub fn mouse_interaction(
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
is_enabled: bool, is_enabled: bool,
) -> mouse::Interaction { ) -> 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 { if is_mouse_over && is_enabled {
mouse::Interaction::Pointer mouse::Interaction::Pointer

View file

@ -1,10 +1,8 @@
//! Draw 2D graphics for your users. //! Draw 2D graphics for your users.
pub mod event; pub mod event;
mod cursor;
mod program; mod program;
pub use cursor::Cursor;
pub use event::Event; pub use event::Event;
pub use program::Program; pub use program::Program;
@ -17,7 +15,7 @@ use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::{Clipboard, Element, Shell, Widget}; 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 crate::graphics::geometry;
use std::marker::PhantomData; 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: /// If you want to get a quick overview, here's how we can draw a simple circle:
/// ///
/// ```no_run /// ```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::{Color, Rectangle};
/// # use iced_widget::core::mouse;
/// # use iced_widget::style::Theme; /// # use iced_widget::style::Theme;
/// # /// #
/// # pub type Renderer = iced_widget::renderer::Renderer<Theme>; /// # pub type Renderer = iced_widget::renderer::Renderer<Theme>;
@ -43,7 +42,7 @@ use std::marker::PhantomData;
/// impl Program<()> for Circle { /// impl Program<()> for Circle {
/// type State = (); /// 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` /// // We prepare a new `Frame`
/// let mut frame = Frame::new(renderer, bounds.size()); /// let mut frame = Frame::new(renderer, bounds.size());
/// ///
@ -144,7 +143,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: core::Event, event: core::Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -160,8 +159,6 @@ where
_ => None, _ => None,
}; };
let cursor = Cursor::from_window_position(cursor_position);
if let Some(canvas_event) = canvas_event { if let Some(canvas_event) = canvas_event {
let state = tree.state.downcast_mut::<P::State>(); let state = tree.state.downcast_mut::<P::State>();
@ -182,12 +179,11 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
let bounds = layout.bounds(); let bounds = layout.bounds();
let cursor = Cursor::from_window_position(cursor_position);
let state = tree.state.downcast_ref::<P::State>(); let state = tree.state.downcast_ref::<P::State>();
self.program.mouse_interaction(state, bounds, cursor) self.program.mouse_interaction(state, bounds, cursor)
@ -200,7 +196,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let bounds = layout.bounds();
@ -209,7 +205,6 @@ where
return; return;
} }
let cursor = Cursor::from_window_position(cursor_position);
let state = tree.state.downcast_ref::<P::State>(); let state = tree.state.downcast_ref::<P::State>();
renderer.with_translation( renderer.with_translation(

View file

@ -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,
}
}
}

View file

@ -1,6 +1,5 @@
use crate::canvas::event::{self, Event}; use crate::canvas::event::{self, Event};
use crate::canvas::mouse; use crate::canvas::mouse;
use crate::canvas::Cursor;
use crate::core::Rectangle; use crate::core::Rectangle;
use crate::graphics::geometry::{self, Geometry}; use crate::graphics::geometry::{self, Geometry};
@ -33,7 +32,7 @@ where
_state: &mut Self::State, _state: &mut Self::State,
_event: Event, _event: Event,
_bounds: Rectangle, _bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> (event::Status, Option<Message>) { ) -> (event::Status, Option<Message>) {
(event::Status::Ignored, None) (event::Status::Ignored, None)
} }
@ -51,7 +50,7 @@ where
renderer: &Renderer, renderer: &Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> Vec<Geometry>; ) -> Vec<Geometry>;
/// Returns the current mouse interaction of the [`Program`]. /// Returns the current mouse interaction of the [`Program`].
@ -64,7 +63,7 @@ where
&self, &self,
_state: &Self::State, _state: &Self::State,
_bounds: Rectangle, _bounds: Rectangle,
_cursor: Cursor, _cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse::Interaction::default() mouse::Interaction::default()
} }
@ -82,7 +81,7 @@ where
state: &mut Self::State, state: &mut Self::State,
event: Event, event: Event,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> (event::Status, Option<Message>) { ) -> (event::Status, Option<Message>) {
T::update(self, state, event, bounds, cursor) T::update(self, state, event, bounds, cursor)
} }
@ -93,7 +92,7 @@ where
renderer: &Renderer, renderer: &Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> Vec<Geometry> { ) -> Vec<Geometry> {
T::draw(self, state, renderer, theme, bounds, cursor) T::draw(self, state, renderer, theme, bounds, cursor)
} }
@ -102,7 +101,7 @@ where
&self, &self,
state: &Self::State, state: &Self::State,
bounds: Rectangle, bounds: Rectangle,
cursor: Cursor, cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
T::mouse_interaction(self, state, bounds, cursor) T::mouse_interaction(self, state, bounds, cursor)
} }

View file

@ -8,8 +8,8 @@ use crate::core::text;
use crate::core::touch; use crate::core::touch;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, Alignment, Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell,
Shell, Widget, Widget,
}; };
use crate::{Row, Text}; use crate::{Row, Text};
@ -204,7 +204,7 @@ where
_tree: &mut Tree, _tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -212,7 +212,7 @@ where
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let mouse_over = layout.bounds().contains(cursor_position); let mouse_over = cursor.is_over(&layout.bounds());
if mouse_over { if mouse_over {
shell.publish((self.on_toggle)(!self.is_checked)); shell.publish((self.on_toggle)(!self.is_checked));
@ -230,11 +230,11 @@ where
&self, &self,
_tree: &Tree, _tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
if layout.bounds().contains(cursor_position) { if cursor.is_over(&layout.bounds()) {
mouse::Interaction::Pointer mouse::Interaction::Pointer
} else { } else {
mouse::Interaction::default() mouse::Interaction::default()
@ -248,11 +248,10 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let is_mouse_over = cursor.is_over(&layout.bounds());
let is_mouse_over = bounds.contains(cursor_position);
let mut children = layout.children(); let mut children = layout.children();

View file

@ -6,8 +6,8 @@ use crate::core::overlay;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::{Operation, Tree}; use crate::core::widget::{Operation, Tree};
use crate::core::{ use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Point, Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle,
Rectangle, Shell, Widget, Shell, Widget,
}; };
/// A container that distributes its contents vertically. /// A container that distributes its contents vertically.
@ -166,7 +166,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -180,7 +180,7 @@ where
state, state,
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -193,7 +193,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -203,11 +203,7 @@ where
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), layout)| {
child.as_widget().mouse_interaction( child.as_widget().mouse_interaction(
state, state, layout, cursor, viewport, renderer,
layout,
cursor_position,
viewport,
renderer,
) )
}) })
.max() .max()
@ -221,7 +217,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
for ((child, state), layout) in self for ((child, state), layout) in self
@ -230,15 +226,9 @@ where
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
{ {
child.as_widget().draw( child
state, .as_widget()
renderer, .draw(state, renderer, theme, style, layout, cursor, viewport);
theme,
style,
layout,
cursor_position,
viewport,
);
} }
} }

View file

@ -196,7 +196,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -205,7 +205,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event, event,
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -216,14 +216,14 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -236,7 +236,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
renderer_style: &renderer::Style, renderer_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
let style = theme.appearance(&self.style); let style = theme.appearance(&self.style);
@ -253,7 +253,7 @@ where
.unwrap_or(renderer_style.text_color), .unwrap_or(renderer_style.text_color),
}, },
layout.children().next().unwrap(), layout.children().next().unwrap(),
cursor_position, cursor,
viewport, viewport,
); );
} }

View file

@ -4,10 +4,11 @@ pub use viewer::Viewer;
use crate::core::image; use crate::core::image;
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget, ContentFit, Element, Layout, Length, Rectangle, Size, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -186,7 +187,7 @@ where
_theme: &Renderer::Theme, _theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw(renderer, layout, &self.handle, self.content_fit) draw(renderer, layout, &self.handle, self.content_fit)

View file

@ -144,18 +144,19 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_shell: &mut Shell<'_, Message>, _shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position);
match event { match event {
Event::Mouse(mouse::Event::WheelScrolled { delta }) Event::Mouse(mouse::Event::WheelScrolled { delta }) => {
if is_mouse_over => let Some(cursor_position) = cursor.position() else {
{ return event::Status::Ignored;
};
match delta { match delta {
mouse::ScrollDelta::Lines { y, .. } mouse::ScrollDelta::Lines { y, .. }
| mouse::ScrollDelta::Pixels { y, .. } => { | mouse::ScrollDelta::Pixels { y, .. } => {
@ -205,9 +206,11 @@ where
event::Status::Captured event::Status::Captured
} }
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
if is_mouse_over => let Some(cursor_position) = cursor.position() else {
{ return event::Status::Ignored;
};
let state = tree.state.downcast_mut::<State>(); let state = tree.state.downcast_mut::<State>();
state.cursor_grabbed_at = Some(cursor_position); state.cursor_grabbed_at = Some(cursor_position);
@ -277,13 +280,13 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
let state = tree.state.downcast_ref::<State>(); let state = tree.state.downcast_ref::<State>();
let bounds = layout.bounds(); 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() { if state.is_cursor_grabbed() {
mouse::Interaction::Grabbing mouse::Interaction::Grabbing
@ -301,7 +304,7 @@ where
_theme: &Renderer::Theme, _theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let state = tree.state.downcast_ref::<State>(); let state = tree.state.downcast_ref::<State>();

View file

@ -181,7 +181,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -191,7 +191,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -203,7 +203,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -211,7 +211,7 @@ where
element.as_widget().mouse_interaction( element.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -225,7 +225,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.with_element(|element| { self.with_element(|element| {
@ -235,7 +235,7 @@ where
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
) )
}) })
@ -342,27 +342,22 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
let _ = self.with_overlay_maybe(|overlay| { let _ = self.with_overlay_maybe(|overlay| {
overlay.draw(renderer, theme, style, layout, cursor_position); overlay.draw(renderer, theme, style, layout, cursor);
}); });
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.mouse_interaction( overlay.mouse_interaction(layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
}) })
.unwrap_or_default() .unwrap_or_default()
} }
@ -371,20 +366,13 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.with_overlay_mut_maybe(|overlay| { self.with_overlay_mut_maybe(|overlay| {
overlay.on_event( overlay.on_event(event, layout, cursor, renderer, clipboard, shell)
event,
layout,
cursor_position,
renderer,
clipboard,
shell,
)
}) })
.unwrap_or(event::Status::Ignored) .unwrap_or(event::Status::Ignored)
} }

View file

@ -265,7 +265,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: core::Event, event: core::Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -279,7 +279,7 @@ where
&mut t.borrow_mut().as_mut().unwrap().children[0], &mut t.borrow_mut().as_mut().unwrap().children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,
@ -397,7 +397,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>(); let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>();
@ -408,7 +408,7 @@ where
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
}); });
@ -418,7 +418,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -427,7 +427,7 @@ where
element.as_widget().mouse_interaction( element.as_widget().mouse_interaction(
&tree.borrow().as_ref().unwrap().children[0], &tree.borrow().as_ref().unwrap().children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -569,27 +569,22 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
let _ = self.with_overlay_maybe(|overlay| { let _ = self.with_overlay_maybe(|overlay| {
overlay.draw(renderer, theme, style, layout, cursor_position); overlay.draw(renderer, theme, style, layout, cursor);
}); });
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.mouse_interaction( overlay.mouse_interaction(layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
}) })
.unwrap_or_default() .unwrap_or_default()
} }
@ -598,7 +593,7 @@ where
&mut self, &mut self,
event: core::Event, event: core::Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -611,7 +606,7 @@ where
overlay.on_event( overlay.on_event(
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,

View file

@ -177,7 +177,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -198,7 +198,7 @@ where
tree, tree,
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut local_shell, &mut local_shell,
@ -222,7 +222,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
let state = tree.state.downcast_ref::<State>(); let state = tree.state.downcast_ref::<State>();
@ -235,13 +235,7 @@ where
&self.view, &self.view,
|tree, renderer, layout, element| { |tree, renderer, layout, element| {
element.as_widget().draw( element.as_widget().draw(
tree, tree, renderer, theme, style, layout, cursor, viewport,
renderer,
theme,
style,
layout,
cursor_position,
viewport,
) )
}, },
) )
@ -251,7 +245,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -264,13 +258,9 @@ where
layout, layout,
&self.view, &self.view,
|tree, renderer, layout, element| { |tree, renderer, layout, element| {
element.as_widget().mouse_interaction( element
tree, .as_widget()
layout, .mouse_interaction(tree, layout, cursor, viewport, renderer)
cursor_position,
viewport,
renderer,
)
}, },
) )
} }
@ -384,27 +374,22 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
let _ = self.with_overlay_maybe(|overlay| { let _ = self.with_overlay_maybe(|overlay| {
overlay.draw(renderer, theme, style, layout, cursor_position); overlay.draw(renderer, theme, style, layout, cursor);
}); });
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.mouse_interaction( overlay.mouse_interaction(layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
}) })
.unwrap_or_default() .unwrap_or_default()
} }
@ -413,20 +398,13 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.with_overlay_mut_maybe(|overlay| { self.with_overlay_mut_maybe(|overlay| {
overlay.on_event( overlay.on_event(event, layout, cursor, renderer, clipboard, shell)
event,
layout,
cursor_position,
renderer,
clipboard,
shell,
)
}) })
.unwrap_or(event::Status::Ignored) .unwrap_or(event::Status::Ignored)
} }

View file

@ -8,7 +8,7 @@ use crate::core::renderer;
use crate::core::touch; use crate::core::touch;
use crate::core::widget::{tree, Operation, Tree}; use crate::core::widget::{tree, Operation, Tree};
use crate::core::{ use crate::core::{
Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget, Clipboard, Element, Layout, Length, Rectangle, Shell, Widget,
}; };
/// Emit messages on mouse events. /// Emit messages on mouse events.
@ -146,7 +146,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -155,7 +155,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -163,21 +163,21 @@ where
return event::Status::Captured; return event::Status::Captured;
} }
update(self, &event, layout, cursor_position, shell) update(self, &event, layout, cursor, shell)
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -190,7 +190,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
renderer_style: &renderer::Style, renderer_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.content.as_widget().draw( self.content.as_widget().draw(
@ -199,7 +199,7 @@ where
theme, theme,
renderer_style, renderer_style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -237,10 +237,10 @@ fn update<Message: Clone, Renderer>(
widget: &mut MouseArea<'_, Message, Renderer>, widget: &mut MouseArea<'_, Message, Renderer>,
event: &Event, event: &Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
if !layout.bounds().contains(cursor_position) { if !cursor.is_over(&layout.bounds()) {
return event::Status::Ignored; return event::Status::Ignored;
} }

View file

@ -259,36 +259,25 @@ where
&mut self, &mut self,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.container.on_event( self.container.on_event(
self.state, self.state, event, layout, cursor, renderer, clipboard, shell,
event,
layout,
cursor_position,
renderer,
clipboard,
shell,
) )
} }
fn mouse_interaction( fn mouse_interaction(
&self, &self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.container.mouse_interaction( self.container
self.state, .mouse_interaction(self.state, layout, cursor, viewport, renderer)
layout,
cursor_position,
viewport,
renderer,
)
} }
fn draw( fn draw(
@ -297,7 +286,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) { ) {
let appearance = theme.appearance(&self.style); let appearance = theme.appearance(&self.style);
let bounds = layout.bounds(); let bounds = layout.bounds();
@ -312,15 +301,8 @@ where
appearance.background, appearance.background,
); );
self.container.draw( self.container
self.state, .draw(self.state, renderer, theme, style, layout, cursor, &bounds);
renderer,
theme,
style,
layout,
cursor_position,
&bounds,
);
} }
} }
@ -387,7 +369,7 @@ where
_state: &mut Tree, _state: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_shell: &mut Shell<'_, Message>, _shell: &mut Shell<'_, Message>,
@ -396,7 +378,7 @@ where
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if cursor.is_over(&bounds) {
if let Some(index) = *self.hovered_option { if let Some(index) = *self.hovered_option {
if let Some(option) = self.options.get(index) { if let Some(option) = self.options.get(index) {
*self.last_selection = Some(option.clone()); *self.last_selection = Some(option.clone());
@ -405,9 +387,9 @@ where
} }
} }
Event::Mouse(mouse::Event::CursorMoved { .. }) => { Event::Mouse(mouse::Event::CursorMoved { .. }) => {
let bounds = layout.bounds(); if let Some(cursor_position) =
cursor.position_in(&layout.bounds())
if bounds.contains(cursor_position) { {
let text_size = self let text_size = self
.text_size .text_size
.unwrap_or_else(|| renderer.default_size()); .unwrap_or_else(|| renderer.default_size());
@ -416,16 +398,14 @@ where
self.text_line_height.to_absolute(Pixels(text_size)), self.text_line_height.to_absolute(Pixels(text_size)),
) + self.padding.vertical(); ) + self.padding.vertical();
*self.hovered_option = Some( *self.hovered_option =
((cursor_position.y - bounds.y) / option_height) Some((cursor_position.y / option_height) as usize);
as usize,
);
} }
} }
Event::Touch(touch::Event::FingerPressed { .. }) => { Event::Touch(touch::Event::FingerPressed { .. }) => {
let bounds = layout.bounds(); if let Some(cursor_position) =
cursor.position_in(&layout.bounds())
if bounds.contains(cursor_position) { {
let text_size = self let text_size = self
.text_size .text_size
.unwrap_or_else(|| renderer.default_size()); .unwrap_or_else(|| renderer.default_size());
@ -434,10 +414,8 @@ where
self.text_line_height.to_absolute(Pixels(text_size)), self.text_line_height.to_absolute(Pixels(text_size)),
) + self.padding.vertical(); ) + self.padding.vertical();
*self.hovered_option = Some( *self.hovered_option =
((cursor_position.y - bounds.y) / option_height) Some((cursor_position.y / option_height) as usize);
as usize,
);
if let Some(index) = *self.hovered_option { if let Some(index) = *self.hovered_option {
if let Some(option) = self.options.get(index) { if let Some(option) = self.options.get(index) {
@ -456,11 +434,11 @@ where
&self, &self,
_state: &Tree, _state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
let is_mouse_over = layout.bounds().contains(cursor_position); let is_mouse_over = cursor.is_over(&layout.bounds());
if is_mouse_over { if is_mouse_over {
mouse::Interaction::Pointer mouse::Interaction::Pointer
@ -476,7 +454,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
let appearance = theme.appearance(&self.style); let appearance = theme.appearance(&self.style);

View file

@ -313,7 +313,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -331,7 +331,7 @@ where
self.contents.layout(), self.contents.layout(),
&event, &event,
layout, layout,
cursor_position, cursor,
shell, shell,
self.spacing, self.spacing,
self.contents.iter(), self.contents.iter(),
@ -353,7 +353,7 @@ where
tree, tree,
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -367,7 +367,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -375,7 +375,7 @@ where
tree.state.downcast_ref(), tree.state.downcast_ref(),
self.contents.layout(), self.contents.layout(),
layout, layout,
cursor_position, cursor,
self.spacing, self.spacing,
self.on_resize.as_ref().map(|(leeway, _)| *leeway), self.on_resize.as_ref().map(|(leeway, _)| *leeway),
) )
@ -388,7 +388,7 @@ where
content.mouse_interaction( content.mouse_interaction(
tree, tree,
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
self.drag_enabled(), self.drag_enabled(),
@ -406,14 +406,14 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
draw( draw(
tree.state.downcast_ref(), tree.state.downcast_ref(),
self.contents.layout(), self.contents.layout(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
theme, theme,
style, style,
@ -425,20 +425,9 @@ where
.iter() .iter()
.zip(&tree.children) .zip(&tree.children)
.map(|((pane, content), tree)| (pane, (content, tree))), .map(|((pane, content), tree)| (pane, (content, tree))),
|(content, tree), |(content, tree), renderer, style, layout, cursor, rectangle| {
renderer,
style,
layout,
cursor_position,
rectangle| {
content.draw( content.draw(
tree, tree, renderer, theme, style, layout, cursor, rectangle,
renderer,
theme,
style,
layout,
cursor_position,
rectangle,
); );
}, },
) )
@ -520,7 +509,7 @@ pub fn update<'a, Message, T: Draggable>(
node: &Node, node: &Node,
event: &Event, event: &Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
spacing: f32, spacing: f32,
contents: impl Iterator<Item = (Pane, T)>, contents: impl Iterator<Item = (Pane, T)>,
@ -535,7 +524,7 @@ pub fn update<'a, Message, T: Draggable>(
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if let Some(cursor_position) = cursor.position_over(&bounds) {
event_status = event::Status::Captured; event_status = event::Status::Captured;
match on_resize { match on_resize {
@ -592,14 +581,18 @@ pub fn update<'a, Message, T: Draggable>(
| Event::Touch(touch::Event::FingerLost { .. }) => { | Event::Touch(touch::Event::FingerLost { .. }) => {
if let Some((pane, _)) = action.picked_pane() { if let Some((pane, _)) = action.picked_pane() {
if let Some(on_drag) = on_drag { if let Some(on_drag) = on_drag {
let mut dropped_region = contents let dropped_region =
.zip(layout.children()) cursor.position().and_then(|cursor_position| {
.filter_map(|(target, layout)| { contents
layout_region(layout, cursor_position) .zip(layout.children())
.map(|region| (target, region)) .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 => { Some(((target, _), region)) if pane != target => {
DragEvent::Dropped { DragEvent::Dropped {
pane, pane,
@ -634,24 +627,32 @@ pub fn update<'a, Message, T: Draggable>(
); );
if let Some((axis, rectangle, _)) = splits.get(&split) { if let Some((axis, rectangle, _)) = splits.get(&split) {
let ratio = match axis { if let Some(cursor_position) = cursor.position() {
Axis::Horizontal => { let ratio = match axis {
let position = Axis::Horizontal => {
cursor_position.y - bounds.y - rectangle.y; let position = cursor_position.y
- bounds.y
- rectangle.y;
(position / rectangle.height).clamp(0.1, 0.9) (position / rectangle.height)
} .clamp(0.1, 0.9)
Axis::Vertical => { }
let position = Axis::Vertical => {
cursor_position.x - bounds.x - rectangle.x; let position = cursor_position.x
- bounds.x
- rectangle.x;
(position / rectangle.width).clamp(0.1, 0.9) (position / rectangle.width).clamp(0.1, 0.9)
} }
}; };
shell.publish(on_resize(ResizeEvent { split, ratio })); shell.publish(on_resize(ResizeEvent {
split,
ratio,
}));
event_status = event::Status::Captured; event_status = event::Status::Captured;
}
} }
} }
} }
@ -724,7 +725,7 @@ pub fn mouse_interaction(
action: &state::Action, action: &state::Action,
node: &Node, node: &Node,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
spacing: f32, spacing: f32,
resize_leeway: Option<f32>, resize_leeway: Option<f32>,
) -> Option<mouse::Interaction> { ) -> Option<mouse::Interaction> {
@ -735,6 +736,7 @@ pub fn mouse_interaction(
let resize_axis = let resize_axis =
action.picked_split().map(|(_, axis)| axis).or_else(|| { action.picked_split().map(|(_, axis)| axis).or_else(|| {
resize_leeway.and_then(|leeway| { resize_leeway.and_then(|leeway| {
let cursor_position = cursor.position()?;
let bounds = layout.bounds(); let bounds = layout.bounds();
let splits = node.split_regions(spacing, bounds.size()); let splits = node.split_regions(spacing, bounds.size());
@ -764,7 +766,7 @@ pub fn draw<Renderer, T>(
action: &state::Action, action: &state::Action,
node: &Node, node: &Node,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
default_style: &renderer::Style, default_style: &renderer::Style,
@ -778,7 +780,7 @@ pub fn draw<Renderer, T>(
&mut Renderer, &mut Renderer,
&renderer::Style, &renderer::Style,
Layout<'_>, Layout<'_>,
Point, mouse::Cursor,
&Rectangle, &Rectangle,
), ),
) where ) where
@ -802,6 +804,7 @@ pub fn draw<Renderer, T>(
}) })
.or_else(|| match resize_leeway { .or_else(|| match resize_leeway {
Some(leeway) => { Some(leeway) => {
let cursor_position = cursor.position()?;
let bounds = layout.bounds(); let bounds = layout.bounds();
let relative_cursor = Point::new( let relative_cursor = Point::new(
@ -822,12 +825,10 @@ pub fn draw<Renderer, T>(
None => None, None => None,
}); });
let pane_cursor_position = if picked_pane.is_some() { let pane_cursor = if picked_pane.is_some() {
// TODO: Remove once cursor availability is encoded in the type mouse::Cursor::Unavailable
// system
Point::new(-1.0, -1.0)
} else { } else {
cursor_position cursor
}; };
let mut render_picked_pane = None; let mut render_picked_pane = None;
@ -843,12 +844,15 @@ pub fn draw<Renderer, T>(
renderer, renderer,
default_style, default_style,
layout, layout,
pane_cursor_position, pane_cursor,
viewport, viewport,
); );
if picked_pane.is_some() { 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 bounds = layout_region_bounds(layout, region);
let hovered_region_style = theme.hovered_region(style); let hovered_region_style = theme.hovered_region(style);
@ -872,7 +876,7 @@ pub fn draw<Renderer, T>(
renderer, renderer,
default_style, default_style,
layout, layout,
pane_cursor_position, pane_cursor,
viewport, viewport,
); );
} }
@ -881,25 +885,27 @@ pub fn draw<Renderer, T>(
// Render picked pane last // Render picked pane last
if let Some((pane, origin, layout)) = render_picked_pane { if let Some((pane, origin, layout)) = render_picked_pane {
let bounds = layout.bounds(); if let Some(cursor_position) = cursor.position() {
let bounds = layout.bounds();
renderer.with_translation( renderer.with_translation(
cursor_position cursor_position
- Point::new(bounds.x + origin.x, bounds.y + origin.y), - Point::new(bounds.x + origin.x, bounds.y + origin.y),
|renderer| { |renderer| {
renderer.with_layer(bounds, |renderer| { renderer.with_layer(bounds, |renderer| {
draw_pane( draw_pane(
pane, pane,
renderer, renderer,
default_style, default_style,
layout, layout,
pane_cursor_position, pane_cursor,
viewport, viewport,
); );
}); });
}, },
); );
}; }
}
if let Some((axis, split_region, is_picked)) = picked_split { if let Some((axis, split_region, is_picked)) = picked_split {
let highlight = if is_picked { let highlight = if is_picked {

View file

@ -95,7 +95,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
use container::StyleSheet; use container::StyleSheet;
@ -113,7 +113,7 @@ where
let title_bar_layout = children.next().unwrap(); let title_bar_layout = children.next().unwrap();
let body_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( self.body.as_widget().draw(
&tree.children[0], &tree.children[0],
@ -121,7 +121,7 @@ where
theme, theme,
style, style,
body_layout, body_layout,
cursor_position, cursor,
viewport, viewport,
); );
@ -131,7 +131,7 @@ where
theme, theme,
style, style,
title_bar_layout, title_bar_layout,
cursor_position, cursor,
viewport, viewport,
show_controls, show_controls,
); );
@ -142,7 +142,7 @@ where
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -218,7 +218,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -233,7 +233,7 @@ where
&mut tree.children[1], &mut tree.children[1],
event.clone(), event.clone(),
children.next().unwrap(), children.next().unwrap(),
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -251,7 +251,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event, event,
body_layout, body_layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -265,42 +265,48 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
drag_enabled: bool, drag_enabled: bool,
) -> mouse::Interaction { ) -> mouse::Interaction {
let (body_layout, title_bar_interaction) = let (body_layout, title_bar_interaction) = if let Some(title_bar) =
if let Some(title_bar) = &self.title_bar { &self.title_bar
let mut children = layout.children(); {
let title_bar_layout = children.next().unwrap(); let mut children = layout.children();
let title_bar_layout = children.next().unwrap();
let is_over_pick_area = title_bar let is_over_pick_area = cursor
.is_over_pick_area(title_bar_layout, cursor_position); .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 { if is_over_pick_area && drag_enabled {
return mouse::Interaction::Grab; return mouse::Interaction::Grab;
} }
let mouse_interaction = title_bar.mouse_interaction( let mouse_interaction = title_bar.mouse_interaction(
&tree.children[1], &tree.children[1],
title_bar_layout, title_bar_layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
); );
(children.next().unwrap(), mouse_interaction) (children.next().unwrap(), mouse_interaction)
} else { } else {
(layout, mouse::Interaction::default()) (layout, mouse::Interaction::default())
}; };
self.body self.body
.as_widget() .as_widget()
.mouse_interaction( .mouse_interaction(
&tree.children[0], &tree.children[0],
body_layout, body_layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )

View file

@ -4,9 +4,5 @@ use crate::core::{Layout, Point};
pub trait Draggable { pub trait Draggable {
/// Returns whether the [`Draggable`] with the given [`Layout`] can be picked /// Returns whether the [`Draggable`] with the given [`Layout`] can be picked
/// at the provided cursor position. /// at the provided cursor position.
fn can_be_dragged_at( fn can_be_dragged_at(&self, layout: Layout<'_>, cursor: Point) -> bool;
&self,
layout: Layout<'_>,
cursor_position: Point,
) -> bool;
} }

View file

@ -122,7 +122,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
inherited_style: &renderer::Style, inherited_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
show_controls: bool, show_controls: bool,
) { ) {
@ -158,7 +158,7 @@ where
theme, theme,
&inherited_style, &inherited_style,
controls_layout, controls_layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -171,7 +171,7 @@ where
theme, theme,
&inherited_style, &inherited_style,
title_layout, title_layout,
cursor_position, cursor,
viewport, viewport,
); );
} }
@ -300,7 +300,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -324,7 +324,7 @@ where
&mut tree.children[1], &mut tree.children[1],
event.clone(), event.clone(),
controls_layout, controls_layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -338,7 +338,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event, event,
title_layout, title_layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -354,7 +354,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -367,7 +367,7 @@ where
let title_interaction = self.content.as_widget().mouse_interaction( let title_interaction = self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
title_layout, title_layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
); );
@ -377,7 +377,7 @@ where
let controls_interaction = controls.as_widget().mouse_interaction( let controls_interaction = controls.as_widget().mouse_interaction(
&tree.children[1], &tree.children[1],
controls_layout, controls_layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
); );

View file

@ -11,8 +11,8 @@ use crate::core::text::{self, Text};
use crate::core::touch; use crate::core::touch;
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::{ use crate::core::{
Clipboard, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, Shell,
Shell, Size, Widget, Size, Widget,
}; };
use crate::overlay::menu::{self, Menu}; use crate::overlay::menu::{self, Menu};
use crate::scrollable; use crate::scrollable;
@ -196,7 +196,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -204,7 +204,7 @@ where
update( update(
event, event,
layout, layout,
cursor_position, cursor,
shell, shell,
self.on_selected.as_ref(), self.on_selected.as_ref(),
self.selected.as_ref(), self.selected.as_ref(),
@ -217,11 +217,11 @@ where
&self, &self,
_tree: &Tree, _tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction(layout, cursor_position) mouse_interaction(layout, cursor)
} }
fn draw( fn draw(
@ -231,7 +231,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let font = self.font.unwrap_or_else(|| renderer.default_font()); let font = self.font.unwrap_or_else(|| renderer.default_font());
@ -239,7 +239,7 @@ where
renderer, renderer,
theme, theme,
layout, layout,
cursor_position, cursor,
self.padding, self.padding,
self.text_size, self.text_size,
self.text_line_height, self.text_line_height,
@ -431,7 +431,7 @@ where
pub fn update<'a, T, Message>( pub fn update<'a, T, Message>(
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
on_selected: &dyn Fn(T) -> Message, on_selected: &dyn Fn(T) -> Message,
selected: Option<&T>, selected: Option<&T>,
@ -452,7 +452,7 @@ where
state.is_open = false; state.is_open = false;
event::Status::Captured event::Status::Captured
} else if layout.bounds().contains(cursor_position) { } else if cursor.is_over(&layout.bounds()) {
state.is_open = true; state.is_open = true;
state.hovered_option = state.hovered_option =
options.iter().position(|option| Some(option) == selected); options.iter().position(|option| Some(option) == selected);
@ -478,7 +478,7 @@ where
let state = state(); let state = state();
if state.keyboard_modifiers.command() if state.keyboard_modifiers.command()
&& layout.bounds().contains(cursor_position) && cursor.is_over(&layout.bounds())
&& !state.is_open && !state.is_open
{ {
fn find_next<'a, T: PartialEq>( fn find_next<'a, T: PartialEq>(
@ -529,10 +529,10 @@ where
/// Returns the current [`mouse::Interaction`] of a [`PickList`]. /// Returns the current [`mouse::Interaction`] of a [`PickList`].
pub fn mouse_interaction( pub fn mouse_interaction(
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over = cursor.is_over(&bounds);
if is_mouse_over { if is_mouse_over {
mouse::Interaction::Pointer mouse::Interaction::Pointer
@ -593,7 +593,7 @@ pub fn draw<'a, T, Renderer>(
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
padding: Padding, padding: Padding,
text_size: Option<f32>, text_size: Option<f32>,
text_line_height: text::LineHeight, text_line_height: text::LineHeight,
@ -610,7 +610,7 @@ pub fn draw<'a, T, Renderer>(
T: ToString + 'a, T: ToString + 'a,
{ {
let bounds = layout.bounds(); 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 is_selected = selected.is_some();
let style = if is_mouse_over { let style = if is_mouse_over {

View file

@ -1,10 +1,9 @@
//! Provide progress feedback to your users. //! Provide progress feedback to your users.
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{Color, Element, Layout, Length, Rectangle, Size, Widget};
Color, Element, Layout, Length, Point, Rectangle, Size, Widget,
};
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
@ -115,7 +114,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let bounds = layout.bounds();

View file

@ -1,6 +1,7 @@
//! Encode and display information in a QR code. //! Encode and display information in a QR code.
use crate::canvas; use crate::canvas;
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer::{self, Renderer as _}; use crate::core::renderer::{self, Renderer as _};
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
@ -74,7 +75,7 @@ impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> {
_theme: &Theme, _theme: &Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let bounds = layout.bounds();

View file

@ -8,8 +8,8 @@ use crate::core::text;
use crate::core::touch; use crate::core::touch;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
Alignment, Clipboard, Color, Element, Layout, Length, Pixels, Point, Alignment, Clipboard, Color, Element, Layout, Length, Pixels, Rectangle,
Rectangle, Shell, Widget, Shell, Widget,
}; };
use crate::{Row, Text}; use crate::{Row, Text};
@ -229,7 +229,7 @@ where
_state: &mut Tree, _state: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -237,7 +237,7 @@ where
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
if layout.bounds().contains(cursor_position) { if cursor.is_over(&layout.bounds()) {
shell.publish(self.on_click.clone()); shell.publish(self.on_click.clone());
return event::Status::Captured; return event::Status::Captured;
@ -253,11 +253,11 @@ where
&self, &self,
_state: &Tree, _state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
if layout.bounds().contains(cursor_position) { if cursor.is_over(&layout.bounds()) {
mouse::Interaction::Pointer mouse::Interaction::Pointer
} else { } else {
mouse::Interaction::default() mouse::Interaction::default()
@ -271,11 +271,10 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let is_mouse_over = cursor.is_over(&layout.bounds());
let is_mouse_over = bounds.contains(cursor_position);
let mut children = layout.children(); let mut children = layout.children();

View file

@ -6,8 +6,8 @@ use crate::core::overlay;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::{Operation, Tree}; use crate::core::widget::{Operation, Tree};
use crate::core::{ use crate::core::{
Alignment, Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, Alignment, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell,
Shell, Widget, Widget,
}; };
/// A container that distributes its contents horizontally. /// A container that distributes its contents horizontally.
@ -155,7 +155,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -169,7 +169,7 @@ where
state, state,
event.clone(), event.clone(),
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -182,7 +182,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
@ -192,11 +192,7 @@ where
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), layout)| {
child.as_widget().mouse_interaction( child.as_widget().mouse_interaction(
state, state, layout, cursor, viewport, renderer,
layout,
cursor_position,
viewport,
renderer,
) )
}) })
.max() .max()
@ -210,7 +206,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
for ((child, state), layout) in self for ((child, state), layout) in self
@ -219,15 +215,9 @@ where
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
{ {
child.as_widget().draw( child
state, .as_widget()
renderer, .draw(state, renderer, theme, style, layout, cursor, viewport);
theme,
style,
layout,
cursor_position,
viewport,
);
} }
} }

View file

@ -1,9 +1,10 @@
//! Display a horizontal or vertical rule for dividing content. //! Display a horizontal or vertical rule for dividing content.
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ 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}; pub use crate::style::rule::{Appearance, FillMode, StyleSheet};
@ -86,7 +87,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let bounds = layout.bounds(); let bounds = layout.bounds();

View file

@ -222,7 +222,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -231,18 +231,18 @@ where
tree.state.downcast_mut::<State>(), tree.state.downcast_mut::<State>(),
event, event,
layout, layout,
cursor_position, cursor,
clipboard, clipboard,
shell, shell,
&self.vertical, &self.vertical,
self.horizontal.as_ref(), self.horizontal.as_ref(),
&self.on_scroll, &self.on_scroll,
|event, layout, cursor_position, clipboard, shell| { |event, layout, cursor, clipboard, shell| {
self.content.as_widget_mut().on_event( self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -258,7 +258,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw( draw(
@ -266,18 +266,18 @@ where
renderer, renderer,
theme, theme,
layout, layout,
cursor_position, cursor,
&self.vertical, &self.vertical,
self.horizontal.as_ref(), self.horizontal.as_ref(),
&self.style, &self.style,
|renderer, layout, cursor_position, viewport| { |renderer, layout, cursor, viewport| {
self.content.as_widget().draw( self.content.as_widget().draw(
&tree.children[0], &tree.children[0],
renderer, renderer,
theme, theme,
style, style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
) )
}, },
@ -288,21 +288,21 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction( mouse_interaction(
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
layout, layout,
cursor_position, cursor,
&self.vertical, &self.vertical,
self.horizontal.as_ref(), self.horizontal.as_ref(),
|layout, cursor_position, viewport| { |layout, cursor, viewport| {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -428,7 +428,7 @@ pub fn update<Message>(
state: &mut State, state: &mut State,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
vertical: &Properties, vertical: &Properties,
@ -437,13 +437,13 @@ pub fn update<Message>(
update_content: impl FnOnce( update_content: impl FnOnce(
Event, Event,
Layout<'_>, Layout<'_>,
Point, mouse::Cursor,
&mut dyn Clipboard, &mut dyn Clipboard,
&mut Shell<'_, Message>, &mut Shell<'_, Message>,
) -> event::Status, ) -> event::Status,
) -> event::Status { ) -> event::Status {
let bounds = layout.bounds(); 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 = layout.children().next().unwrap();
let content_bounds = content.bounds(); let content_bounds = content.bounds();
@ -452,28 +452,21 @@ pub fn update<Message>(
Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); Scrollbars::new(state, vertical, horizontal, bounds, content_bounds);
let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) =
scrollbars.is_mouse_over(cursor_position); scrollbars.is_mouse_over(cursor);
let event_status = { let event_status = {
let cursor_position = if mouse_over_scrollable let cursor = match cursor_over_scrollable {
&& !(mouse_over_y_scrollbar || mouse_over_x_scrollbar) Some(cursor_position)
{ if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) =>
cursor_position + state.offset(bounds, content_bounds) {
} else { mouse::Cursor::Available(
// TODO: Make `cursor_position` an `Option<Point>` so we can encode cursor_position + state.offset(bounds, content_bounds),
// cursor availability. )
// This will probably happen naturally once we add multi-window }
// support. _ => mouse::Cursor::Unavailable,
Point::new(-1.0, -1.0)
}; };
update_content( update_content(event.clone(), content, cursor, clipboard, shell)
event.clone(),
content,
cursor_position,
clipboard,
shell,
)
}; };
if let event::Status::Captured = event_status { if let event::Status::Captured = event_status {
@ -487,76 +480,71 @@ pub fn update<Message>(
return event::Status::Ignored; return event::Status::Ignored;
} }
if mouse_over_scrollable { let Some(cursor_position) = cursor_over_scrollable else {
match event { return event::Status::Ignored
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 match event {
} Event::Mouse(mouse::Event::WheelScrolled { delta }) => {
mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y), 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.scroll(delta, bounds, content_bounds);
state,
on_scroll, notify_on_scroll(state, on_scroll, bounds, content_bounds, shell);
bounds,
content_bounds, return event::Status::Captured;
shell, }
); 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); 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); notify_on_scroll(
state,
state.scroll_area_touched_at = on_scroll,
Some(cursor_position); bounds,
content_bounds,
notify_on_scroll( shell,
state, );
on_scroll,
bounds,
content_bounds,
shell,
);
}
}
touch::Event::FingerLifted { .. }
| touch::Event::FingerLost { .. } => {
state.scroll_area_touched_at = None;
} }
} }
touch::Event::FingerLifted { .. }
return event::Status::Captured; | touch::Event::FingerLost { .. } => {
state.scroll_area_touched_at = None;
}
} }
_ => {}
return event::Status::Captured;
} }
_ => {}
} }
if let Some(scroller_grabbed_at) = state.y_scroller_grabbed_at { if let Some(scroller_grabbed_at) = state.y_scroller_grabbed_at {
@ -700,17 +688,17 @@ pub fn update<Message>(
pub fn mouse_interaction( pub fn mouse_interaction(
state: &State, state: &State,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
vertical: &Properties, vertical: &Properties,
horizontal: Option<&Properties>, horizontal: Option<&Properties>,
content_interaction: impl FnOnce( content_interaction: impl FnOnce(
Layout<'_>, Layout<'_>,
Point, mouse::Cursor,
&Rectangle, &Rectangle,
) -> mouse::Interaction, ) -> mouse::Interaction,
) -> mouse::Interaction { ) -> mouse::Interaction {
let bounds = layout.bounds(); 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_layout = layout.children().next().unwrap();
let content_bounds = content_layout.bounds(); let content_bounds = content_layout.bounds();
@ -719,7 +707,7 @@ pub fn mouse_interaction(
Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); Scrollbars::new(state, vertical, horizontal, bounds, content_bounds);
let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = 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) if (mouse_over_x_scrollbar || mouse_over_y_scrollbar)
|| state.scrollers_grabbed() || state.scrollers_grabbed()
@ -728,17 +716,18 @@ pub fn mouse_interaction(
} else { } else {
let offset = state.offset(bounds, content_bounds); let offset = state.offset(bounds, content_bounds);
let cursor_position = if mouse_over_scrollable let cursor = match cursor_over_scrollable {
&& !(mouse_over_y_scrollbar || mouse_over_x_scrollbar) Some(cursor_position)
{ if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) =>
cursor_position + offset {
} else { mouse::Cursor::Available(cursor_position + offset)
Point::new(-1.0, -1.0) }
_ => mouse::Cursor::Unavailable,
}; };
content_interaction( content_interaction(
content_layout, content_layout,
cursor_position, cursor,
&Rectangle { &Rectangle {
y: bounds.y + offset.y, y: bounds.y + offset.y,
x: bounds.x + offset.x, x: bounds.x + offset.x,
@ -754,11 +743,11 @@ pub fn draw<Renderer>(
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
vertical: &Properties, vertical: &Properties,
horizontal: Option<&Properties>, horizontal: Option<&Properties>,
style: &<Renderer::Theme as StyleSheet>::Style, 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 ) where
Renderer: crate::core::Renderer, Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet, Renderer::Theme: StyleSheet,
@ -770,18 +759,19 @@ pub fn draw<Renderer>(
let scrollbars = let scrollbars =
Scrollbars::new(state, vertical, horizontal, bounds, content_bounds); 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) = 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 offset = state.offset(bounds, content_bounds);
let cursor_position = if mouse_over_scrollable let cursor = match cursor_over_scrollable {
&& !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) Some(cursor_position)
{ if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) =>
cursor_position + offset {
} else { mouse::Cursor::Available(cursor_position + offset)
Point::new(-1.0, -1.0) }
_ => mouse::Cursor::Unavailable,
}; };
// Draw inner content // Draw inner content
@ -793,7 +783,7 @@ pub fn draw<Renderer>(
draw_content( draw_content(
renderer, renderer,
content_layout, content_layout,
cursor_position, cursor,
&Rectangle { &Rectangle {
y: bounds.y + offset.y, y: bounds.y + offset.y,
x: bounds.x + offset.x, x: bounds.x + offset.x,
@ -858,7 +848,7 @@ pub fn draw<Renderer>(
if let Some(scrollbar) = scrollbars.y { if let Some(scrollbar) = scrollbars.y {
let style = if state.y_scroller_grabbed_at.is_some() { let style = if state.y_scroller_grabbed_at.is_some() {
theme.dragging(style) theme.dragging(style)
} else if mouse_over_scrollable { } else if cursor_over_scrollable.is_some() {
theme.hovered(style, mouse_over_y_scrollbar) theme.hovered(style, mouse_over_y_scrollbar)
} else { } else {
theme.active(style) theme.active(style)
@ -871,7 +861,7 @@ pub fn draw<Renderer>(
if let Some(scrollbar) = scrollbars.x { if let Some(scrollbar) = scrollbars.x {
let style = if state.x_scroller_grabbed_at.is_some() { let style = if state.x_scroller_grabbed_at.is_some() {
theme.dragging_horizontal(style) theme.dragging_horizontal(style)
} else if mouse_over_scrollable { } else if cursor_over_scrollable.is_some() {
theme.hovered_horizontal(style, mouse_over_x_scrollbar) theme.hovered_horizontal(style, mouse_over_x_scrollbar)
} else { } else {
theme.active_horizontal(style) theme.active_horizontal(style)
@ -885,7 +875,7 @@ pub fn draw<Renderer>(
draw_content( draw_content(
renderer, renderer,
content_layout, content_layout,
cursor_position, cursor,
&Rectangle { &Rectangle {
x: bounds.x + offset.x, x: bounds.x + offset.x,
y: bounds.y + offset.y, y: bounds.y + offset.y,
@ -1283,17 +1273,21 @@ impl Scrollbars {
} }
} }
fn is_mouse_over(&self, cursor_position: Point) -> (bool, bool) { fn is_mouse_over(&self, cursor: mouse::Cursor) -> (bool, bool) {
( if let Some(cursor_position) = cursor.position() {
self.y (
.as_ref() self.y
.map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) .as_ref()
.unwrap_or(false), .map(|scrollbar| scrollbar.is_mouse_over(cursor_position))
self.x .unwrap_or(false),
.as_ref() self.x
.map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) .as_ref()
.unwrap_or(false), .map(|scrollbar| scrollbar.is_mouse_over(cursor_position))
) .unwrap_or(false),
)
} else {
(false, false)
}
} }
fn grab_y_scroller(&self, cursor_position: Point) -> Option<f32> { fn grab_y_scroller(&self, cursor_position: Point) -> Option<f32> {

View file

@ -183,7 +183,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -191,7 +191,7 @@ where
update( update(
event, event,
layout, layout,
cursor_position, cursor,
shell, shell,
tree.state.downcast_mut::<State>(), tree.state.downcast_mut::<State>(),
&mut self.value, &mut self.value,
@ -209,13 +209,13 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw( draw(
renderer, renderer,
layout, layout,
cursor_position, cursor,
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
self.value, self.value,
&self.range, &self.range,
@ -228,15 +228,11 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction( mouse_interaction(layout, cursor, tree.state.downcast_ref::<State>())
layout,
cursor_position,
tree.state.downcast_ref::<State>(),
)
} }
} }
@ -260,7 +256,7 @@ where
pub fn update<Message, T>( pub fn update<Message, T>(
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
state: &mut State, state: &mut State,
value: &mut T, value: &mut T,
@ -275,7 +271,7 @@ where
{ {
let is_dragging = state.is_dragging; let is_dragging = state.is_dragging;
let mut change = || { let mut change = |cursor_position: Point| {
let bounds = layout.bounds(); let bounds = layout.bounds();
let new_value = if cursor_position.x <= bounds.x { let new_value = if cursor_position.x <= bounds.x {
*range.start() *range.start()
@ -309,8 +305,10 @@ where
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
if layout.bounds().contains(cursor_position) { if let Some(cursor_position) =
change(); cursor.position_over(&layout.bounds())
{
change(cursor_position);
state.is_dragging = true; state.is_dragging = true;
return event::Status::Captured; return event::Status::Captured;
@ -331,7 +329,7 @@ where
Event::Mouse(mouse::Event::CursorMoved { .. }) Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => { | Event::Touch(touch::Event::FingerMoved { .. }) => {
if is_dragging { if is_dragging {
change(); let _ = cursor.position().map(change);
return event::Status::Captured; return event::Status::Captured;
} }
@ -346,7 +344,7 @@ where
pub fn draw<T, R>( pub fn draw<T, R>(
renderer: &mut R, renderer: &mut R,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
state: &State, state: &State,
value: T, value: T,
range: &RangeInclusive<T>, range: &RangeInclusive<T>,
@ -358,7 +356,7 @@ pub fn draw<T, R>(
R::Theme: StyleSheet, R::Theme: StyleSheet,
{ {
let bounds = layout.bounds(); 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 { let style = if state.is_dragging {
style_sheet.dragging(style) style_sheet.dragging(style)
@ -444,11 +442,11 @@ pub fn draw<T, R>(
/// Computes the current [`mouse::Interaction`] of a [`Slider`]. /// Computes the current [`mouse::Interaction`] of a [`Slider`].
pub fn mouse_interaction( pub fn mouse_interaction(
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
state: &State, state: &State,
) -> mouse::Interaction { ) -> mouse::Interaction {
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over = cursor.is_over(&bounds);
if state.is_dragging { if state.is_dragging {
mouse::Interaction::Grabbing mouse::Interaction::Grabbing

View file

@ -1,9 +1,10 @@
//! Distribute content vertically. //! Distribute content vertically.
use crate::core; use crate::core;
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::Tree; 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. /// An amount of empty space.
/// ///
@ -69,7 +70,7 @@ where
_theme: &Renderer::Theme, _theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
_layout: Layout<'_>, _layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
} }

View file

@ -1,10 +1,11 @@
//! Display vector graphics in your application. //! Display vector graphics in your application.
use crate::core::layout; use crate::core::layout;
use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::svg; use crate::core::svg;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget, ContentFit, Element, Layout, Length, Rectangle, Size, Vector, Widget,
}; };
use std::path::PathBuf; use std::path::PathBuf;
@ -143,7 +144,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
_cursor_position: Point, _cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
let Size { width, height } = renderer.dimensions(&self.handle); let Size { width, height } = renderer.dimensions(&self.handle);

View file

@ -207,14 +207,14 @@ where
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
value: Option<&Value>, value: Option<&Value>,
) { ) {
draw( draw(
renderer, renderer,
theme, theme,
layout, layout,
cursor_position, cursor,
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
value.unwrap_or(&self.value), value.unwrap_or(&self.value),
&self.placeholder, &self.placeholder,
@ -298,7 +298,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -306,7 +306,7 @@ where
update( update(
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -329,14 +329,14 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw( draw(
renderer, renderer,
theme, theme,
layout, layout,
cursor_position, cursor,
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
&self.value, &self.value,
&self.placeholder, &self.placeholder,
@ -354,11 +354,11 @@ where
&self, &self,
_state: &Tree, _state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> 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>( pub fn update<'a, Message, Renderer>(
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -550,10 +550,14 @@ where
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let state = state(); 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(|| { state.is_focused.or_else(|| {
let now = Instant::now(); let now = Instant::now();
@ -566,7 +570,7 @@ where
None None
}; };
if is_clicked { if let Some(cursor_position) = click_position {
let text_layout = layout.children().next().unwrap(); let text_layout = layout.children().next().unwrap();
let target = cursor_position.x - text_layout.bounds().x; let target = cursor_position.x - text_layout.bounds().x;
@ -944,7 +948,7 @@ pub fn draw<Renderer>(
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
state: &State, state: &State,
value: &Value, value: &Value,
placeholder: &str, placeholder: &str,
@ -967,7 +971,7 @@ pub fn draw<Renderer>(
let mut children_layout = layout.children(); let mut children_layout = layout.children();
let text_bounds = children_layout.next().unwrap().bounds(); 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 { let appearance = if is_disabled {
theme.disabled(style) theme.disabled(style)
@ -1154,10 +1158,10 @@ pub fn draw<Renderer>(
/// Computes the current [`mouse::Interaction`] of the [`TextInput`]. /// Computes the current [`mouse::Interaction`] of the [`TextInput`].
pub fn mouse_interaction( pub fn mouse_interaction(
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
is_disabled: bool, is_disabled: bool,
) -> mouse::Interaction { ) -> mouse::Interaction {
if layout.bounds().contains(cursor_position) { if cursor.is_over(&layout.bounds()) {
if is_disabled { if is_disabled {
mouse::Interaction::NotAllowed mouse::Interaction::NotAllowed
} else { } else {

View file

@ -7,8 +7,8 @@ use crate::core::renderer;
use crate::core::text; use crate::core::text;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
Alignment, Clipboard, Element, Event, Layout, Length, Pixels, Point, Alignment, Clipboard, Element, Event, Layout, Length, Pixels, Rectangle,
Rectangle, Shell, Widget, Shell, Widget,
}; };
use crate::{Row, Text}; use crate::{Row, Text};
@ -202,14 +202,14 @@ where
_state: &mut Tree, _state: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { 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 { if mouse_over {
shell.publish((self.on_toggle)(!self.is_toggled)); shell.publish((self.on_toggle)(!self.is_toggled));
@ -227,11 +227,11 @@ where
&self, &self,
_state: &Tree, _state: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
if layout.bounds().contains(cursor_position) { if cursor.is_over(&layout.bounds()) {
mouse::Interaction::Pointer mouse::Interaction::Pointer
} else { } else {
mouse::Interaction::default() mouse::Interaction::default()
@ -245,7 +245,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
/// Makes sure that the border radius of the toggler looks good at every size. /// 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 toggler_layout = children.next().unwrap();
let bounds = toggler_layout.bounds(); 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 { let style = if is_mouse_over {
theme.hovered(&self.style, self.is_toggled) theme.hovered(&self.style, self.is_toggled)

View file

@ -9,7 +9,7 @@ use crate::core::renderer;
use crate::core::text; use crate::core::text;
use crate::core::widget::Tree; use crate::core::widget::Tree;
use crate::core::{ use crate::core::{
Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, Shell, Size, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size,
Vector, Widget, Vector, Widget,
}; };
use crate::Text; use crate::Text;
@ -136,7 +136,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -145,7 +145,7 @@ where
&mut tree.children[0], &mut tree.children[0],
event, event,
layout, layout,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
shell, shell,
@ -156,14 +156,14 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
renderer: &Renderer, renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout, layout,
cursor_position, cursor,
viewport, viewport,
renderer, renderer,
) )
@ -176,7 +176,7 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
inherited_style: &renderer::Style, inherited_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
self.content.as_widget().draw( self.content.as_widget().draw(
@ -185,7 +185,7 @@ where
theme, theme,
inherited_style, inherited_style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
@ -196,7 +196,7 @@ where
theme, theme,
inherited_style, inherited_style,
layout, layout,
cursor_position, cursor,
viewport, viewport,
self.position, self.position,
self.gap, self.gap,
@ -206,7 +206,7 @@ where
|renderer, limits| { |renderer, limits| {
Widget::<(), Renderer>::layout(tooltip, renderer, limits) Widget::<(), Renderer>::layout(tooltip, renderer, limits)
}, },
|renderer, defaults, layout, cursor_position, viewport| { |renderer, defaults, layout, viewport| {
Widget::<(), Renderer>::draw( Widget::<(), Renderer>::draw(
tooltip, tooltip,
&Tree::empty(), &Tree::empty(),
@ -214,7 +214,7 @@ where
theme, theme,
defaults, defaults,
layout, layout,
cursor_position, cursor,
viewport, viewport,
); );
}, },
@ -270,7 +270,7 @@ pub fn draw<Renderer>(
theme: &Renderer::Theme, theme: &Renderer::Theme,
inherited_style: &renderer::Style, inherited_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
position: Position, position: Position,
gap: f32, gap: f32,
@ -278,13 +278,7 @@ pub fn draw<Renderer>(
snap_within_viewport: bool, snap_within_viewport: bool,
style: &<Renderer::Theme as container::StyleSheet>::Style, style: &<Renderer::Theme as container::StyleSheet>::Style,
layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node, layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node,
draw_text: impl FnOnce( draw_text: impl FnOnce(&mut Renderer, &renderer::Style, Layout<'_>, &Rectangle),
&mut Renderer,
&renderer::Style,
Layout<'_>,
Point,
&Rectangle,
),
) where ) where
Renderer: core::Renderer, Renderer: core::Renderer,
Renderer::Theme: container::StyleSheet, Renderer::Theme: container::StyleSheet,
@ -293,7 +287,7 @@ pub fn draw<Renderer>(
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if let Some(cursor_position) = cursor.position_over(&bounds) {
let style = theme.appearance(style); let style = theme.appearance(style);
let defaults = renderer::Style { let defaults = renderer::Style {
@ -380,7 +374,6 @@ pub fn draw<Renderer>(
), ),
&text_layout, &text_layout,
), ),
cursor_position,
viewport, viewport,
) )
}); });

View file

@ -180,7 +180,7 @@ where
tree: &mut Tree, tree: &mut Tree,
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
@ -188,7 +188,7 @@ where
update( update(
event, event,
layout, layout,
cursor_position, cursor,
shell, shell,
tree.state.downcast_mut::<State>(), tree.state.downcast_mut::<State>(),
&mut self.value, &mut self.value,
@ -206,13 +206,13 @@ where
theme: &Renderer::Theme, theme: &Renderer::Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
) { ) {
draw( draw(
renderer, renderer,
layout, layout,
cursor_position, cursor,
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
self.value, self.value,
&self.range, &self.range,
@ -225,15 +225,11 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction( mouse_interaction(layout, cursor, tree.state.downcast_ref::<State>())
layout,
cursor_position,
tree.state.downcast_ref::<State>(),
)
} }
} }
@ -257,7 +253,7 @@ where
pub fn update<Message, T>( pub fn update<Message, T>(
event: Event, event: Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
state: &mut State, state: &mut State,
value: &mut T, value: &mut T,
@ -272,8 +268,9 @@ where
{ {
let is_dragging = state.is_dragging; let is_dragging = state.is_dragging;
let mut change = || { let mut change = |cursor_position: Point| {
let bounds = layout.bounds(); let bounds = layout.bounds();
let new_value = if cursor_position.y >= bounds.y + bounds.height { let new_value = if cursor_position.y >= bounds.y + bounds.height {
*range.start() *range.start()
} else if cursor_position.y <= bounds.y { } else if cursor_position.y <= bounds.y {
@ -307,8 +304,10 @@ where
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
if layout.bounds().contains(cursor_position) { if let Some(cursor_position) =
change(); cursor.position_over(&layout.bounds())
{
change(cursor_position);
state.is_dragging = true; state.is_dragging = true;
return event::Status::Captured; return event::Status::Captured;
@ -329,7 +328,7 @@ where
Event::Mouse(mouse::Event::CursorMoved { .. }) Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => { | Event::Touch(touch::Event::FingerMoved { .. }) => {
if is_dragging { if is_dragging {
change(); let _ = cursor.position().map(change);
return event::Status::Captured; return event::Status::Captured;
} }
@ -344,7 +343,7 @@ where
pub fn draw<T, R>( pub fn draw<T, R>(
renderer: &mut R, renderer: &mut R,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
state: &State, state: &State,
value: T, value: T,
range: &RangeInclusive<T>, range: &RangeInclusive<T>,
@ -356,7 +355,7 @@ pub fn draw<T, R>(
R::Theme: StyleSheet, R::Theme: StyleSheet,
{ {
let bounds = layout.bounds(); 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 { let style = if state.is_dragging {
style_sheet.dragging(style) style_sheet.dragging(style)
@ -442,11 +441,11 @@ pub fn draw<T, R>(
/// Computes the current [`mouse::Interaction`] of a [`VerticalSlider`]. /// Computes the current [`mouse::Interaction`] of a [`VerticalSlider`].
pub fn mouse_interaction( pub fn mouse_interaction(
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor: mouse::Cursor,
state: &State, state: &State,
) -> mouse::Interaction { ) -> mouse::Interaction {
let bounds = layout.bounds(); 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 { if state.is_dragging {
mouse::Interaction::Grabbing mouse::Interaction::Grabbing