Create iced_widget subcrate and re-organize the whole codebase

This commit is contained in:
Héctor Ramón Jiménez 2023-03-04 05:37:11 +01:00
parent c54409d171
commit 3a0d34c024
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
209 changed files with 1959 additions and 2183 deletions

View file

@ -0,0 +1,64 @@
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

@ -0,0 +1,21 @@
//! Handle events of a canvas.
use crate::core::keyboard;
use crate::core::mouse;
use crate::core::touch;
pub use crate::core::event::Status;
/// A [`Canvas`] event.
///
/// [`Canvas`]: crate::widget::Canvas
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Event {
/// A mouse event.
Mouse(mouse::Event),
/// A touch event.
Touch(touch::Event),
/// A keyboard event.
Keyboard(keyboard::Event),
}

View file

@ -0,0 +1,109 @@
use crate::canvas::event::{self, Event};
use crate::canvas::mouse;
use crate::canvas::Cursor;
use crate::core::Rectangle;
use crate::graphics::geometry;
/// The state and logic of a [`Canvas`].
///
/// A [`Program`] can mutate internal state and produce messages for an
/// application.
///
/// [`Canvas`]: crate::widget::Canvas
pub trait Program<Message, Renderer = crate::Renderer>
where
Renderer: geometry::Renderer,
{
/// The internal state mutated by the [`Program`].
type State: Default + 'static;
/// Updates the [`State`](Self::State) of the [`Program`].
///
/// When a [`Program`] is used in a [`Canvas`], the runtime will call this
/// method for each [`Event`].
///
/// This method can optionally return a `Message` to notify an application
/// of any meaningful interactions.
///
/// By default, this method does and returns nothing.
///
/// [`Canvas`]: crate::widget::Canvas
fn update(
&self,
_state: &mut Self::State,
_event: Event,
_bounds: Rectangle,
_cursor: Cursor,
) -> (event::Status, Option<Message>) {
(event::Status::Ignored, None)
}
/// Draws the state of the [`Program`], producing a bunch of [`Geometry`].
///
/// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
/// [`Cache`].
///
/// [`Frame`]: crate::widget::canvas::Frame
/// [`Cache`]: crate::widget::canvas::Cache
fn draw(
&self,
state: &Self::State,
renderer: &Renderer,
theme: &Renderer::Theme,
bounds: Rectangle,
cursor: Cursor,
) -> Vec<Renderer::Geometry>;
/// Returns the current mouse interaction of the [`Program`].
///
/// The interaction returned will be in effect even if the cursor position
/// is out of bounds of the program's [`Canvas`].
///
/// [`Canvas`]: crate::widget::Canvas
fn mouse_interaction(
&self,
_state: &Self::State,
_bounds: Rectangle,
_cursor: Cursor,
) -> mouse::Interaction {
mouse::Interaction::default()
}
}
impl<Message, Renderer, T> Program<Message, Renderer> for &T
where
Renderer: geometry::Renderer,
T: Program<Message, Renderer>,
{
type State = T::State;
fn update(
&self,
state: &mut Self::State,
event: Event,
bounds: Rectangle,
cursor: Cursor,
) -> (event::Status, Option<Message>) {
T::update(self, state, event, bounds, cursor)
}
fn draw(
&self,
state: &Self::State,
renderer: &Renderer,
theme: &Renderer::Theme,
bounds: Rectangle,
cursor: Cursor,
) -> Vec<Renderer::Geometry> {
T::draw(self, state, renderer, theme, bounds, cursor)
}
fn mouse_interaction(
&self,
state: &Self::State,
bounds: Rectangle,
cursor: Cursor,
) -> mouse::Interaction {
T::mouse_interaction(self, state, bounds, cursor)
}
}