diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Cargo.toml | 4 | ||||
-rw-r--r-- | core/src/color.rs | 148 | ||||
-rw-r--r-- | core/src/font.rs | 6 | ||||
-rw-r--r-- | core/src/keyboard.rs | 2 | ||||
-rw-r--r-- | core/src/keyboard/event.rs | 31 | ||||
-rw-r--r-- | core/src/lib.rs | 1 | ||||
-rw-r--r-- | core/src/mouse.rs | 8 | ||||
-rw-r--r-- | core/src/mouse/button.rs | 15 | ||||
-rw-r--r-- | core/src/mouse/event.rs | 57 | ||||
-rw-r--r-- | core/src/mouse/interaction.rs | 20 | ||||
-rw-r--r-- | core/src/point.rs | 10 | ||||
-rw-r--r-- | core/src/rectangle.rs | 84 | ||||
-rw-r--r-- | core/src/size.rs | 25 | ||||
-rw-r--r-- | core/src/vector.rs | 11 |
14 files changed, 395 insertions, 27 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index 837f6aae..b52bf315 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,3 +8,7 @@ license = "MIT" repository = "https://github.com/hecrj/iced" [dependencies] + +[dependencies.palette] +version = "0.5.0" +optional = true diff --git a/core/src/color.rs b/core/src/color.rs index db509b88..a4c3d87c 100644 --- a/core/src/color.rs +++ b/core/src/color.rs @@ -1,10 +1,16 @@ +#[cfg(feature = "palette")] +use palette::rgb::{Srgb, Srgba}; + /// A color in the sRGB color space. -#[derive(Debug, Clone, Copy, PartialEq)] -#[allow(missing_docs)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct Color { + /// Red component, 0.0 - 1.0 pub r: f32, + /// Green component, 0.0 - 1.0 pub g: f32, + /// Blue component, 0.0 - 1.0 pub b: f32, + /// Transparency, 0.0 - 1.0 pub a: f32, } @@ -33,11 +39,45 @@ impl Color { a: 0.0, }; + /// Creates a new [`Color`]. + /// + /// In debug mode, it will panic if the values are not in the correct + /// range: 0.0 - 1.0 + /// + /// [`Color`]: struct.Color.html + pub fn new(r: f32, g: f32, b: f32, a: f32) -> Color { + debug_assert!( + (0.0..=1.0).contains(&r), + "Red component must be on [0, 1]" + ); + debug_assert!( + (0.0..=1.0).contains(&g), + "Green component must be on [0, 1]" + ); + debug_assert!( + (0.0..=1.0).contains(&b), + "Blue component must be on [0, 1]" + ); + debug_assert!( + (0.0..=1.0).contains(&a), + "Alpha component must be on [0, 1]" + ); + + Color { r, g, b, a } + } + /// Creates a [`Color`] from its RGB components. /// /// [`Color`]: struct.Color.html pub const fn from_rgb(r: f32, g: f32, b: f32) -> Color { - Color { r, g, b, a: 1.0 } + Color::from_rgba(r, g, b, 1.0f32) + } + + /// Creates a [`Color`] from its RGBA components. + /// + /// [`Color`]: struct.Color.html + pub const fn from_rgba(r: f32, g: f32, b: f32, a: f32) -> Color { + Color { r, g, b, a } } /// Creates a [`Color`] from its RGB8 components. @@ -80,16 +120,114 @@ impl Color { self.a, ] } + + /// Inverts the [`Color`] in-place. + /// + /// [`Color`]: struct.Color.html + pub fn invert(&mut self) { + self.r = 1.0f32 - self.r; + self.b = 1.0f32 - self.g; + self.g = 1.0f32 - self.b; + } + + /// Returns the inverted [`Color`]. + /// + /// [`Color`]: struct.Color.html + pub fn inverse(self) -> Color { + Color::new(1.0f32 - self.r, 1.0f32 - self.g, 1.0f32 - self.b, self.a) + } } impl From<[f32; 3]> for Color { fn from([r, g, b]: [f32; 3]) -> Self { - Color { r, g, b, a: 1.0 } + Color::new(r, g, b, 1.0) } } impl From<[f32; 4]> for Color { fn from([r, g, b, a]: [f32; 4]) -> Self { - Color { r, g, b, a } + Color::new(r, g, b, a) + } +} + +#[cfg(feature = "palette")] +/// Converts from palette's `Srgba` type to a [`Color`]. +/// +/// [`Color`]: struct.Color.html +impl From<Srgba> for Color { + fn from(srgba: Srgba) -> Self { + Color::new(srgba.red, srgba.green, srgba.blue, srgba.alpha) + } +} + +#[cfg(feature = "palette")] +/// Converts from [`Color`] to palette's `Srgba` type. +/// +/// [`Color`]: struct.Color.html +impl From<Color> for Srgba { + fn from(c: Color) -> Self { + Srgba::new(c.r, c.g, c.b, c.a) + } +} + +#[cfg(feature = "palette")] +/// Converts from palette's `Srgb` type to a [`Color`]. +/// +/// [`Color`]: struct.Color.html +impl From<Srgb> for Color { + fn from(srgb: Srgb) -> Self { + Color::new(srgb.red, srgb.green, srgb.blue, 1.0) + } +} + +#[cfg(feature = "palette")] +/// Converts from [`Color`] to palette's `Srgb` type. +/// +/// [`Color`]: struct.Color.html +/// [`Srgb`]: ../palette/rgb/type.Srgb.html +impl From<Color> for Srgb { + fn from(c: Color) -> Self { + Srgb::new(c.r, c.g, c.b) + } +} + +#[cfg(feature = "palette")] +#[cfg(test)] +mod tests { + use super::*; + use palette::Blend; + + #[test] + fn srgba_traits() { + let c = Color::from_rgb(0.5, 0.4, 0.3); + // Round-trip conversion to the palette:Srgba type + let s: Srgba = c.into(); + let r: Color = s.into(); + assert_eq!(c, r); + } + + #[test] + fn color_manipulation() { + let c1 = Color::from_rgb(0.5, 0.4, 0.3); + let c2 = Color::from_rgb(0.2, 0.5, 0.3); + + // Convert to linear color for manipulation + let l1 = Srgba::from(c1).into_linear(); + let l2 = Srgba::from(c2).into_linear(); + + // Take the lighter of each of the RGB components + let lighter = l1.lighten(l2); + + // Convert back to our Color + let r: Color = Srgba::from_linear(lighter).into(); + assert_eq!( + r, + Color { + r: 0.5, + g: 0.5, + b: 0.3, + a: 1.0 + } + ); } } diff --git a/core/src/font.rs b/core/src/font.rs index be49c825..3f9ad2b5 100644 --- a/core/src/font.rs +++ b/core/src/font.rs @@ -16,3 +16,9 @@ pub enum Font { bytes: &'static [u8], }, } + +impl Default for Font { + fn default() -> Font { + Font::Default + } +} diff --git a/core/src/keyboard.rs b/core/src/keyboard.rs index d98b2989..b26bdb3d 100644 --- a/core/src/keyboard.rs +++ b/core/src/keyboard.rs @@ -1,6 +1,8 @@ //! Reuse basic keyboard types. +mod event; mod key_code; mod modifiers_state; +pub use event::Event; pub use key_code::KeyCode; pub use modifiers_state::ModifiersState; diff --git a/core/src/keyboard/event.rs b/core/src/keyboard/event.rs new file mode 100644 index 00000000..bc8437a8 --- /dev/null +++ b/core/src/keyboard/event.rs @@ -0,0 +1,31 @@ +use super::{KeyCode, ModifiersState}; + +/// A keyboard event. +/// +/// _**Note:** This type is largely incomplete! If you need to track +/// additional events, feel free to [open an issue] and share your use case!_ +/// +/// [open an issue]: https://github.com/hecrj/iced/issues +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Event { + /// A keyboard key was pressed. + KeyPressed { + /// The key identifier + key_code: KeyCode, + + /// The state of the modifier keys + modifiers: ModifiersState, + }, + + /// A keyboard key was released. + KeyReleased { + /// The key identifier + key_code: KeyCode, + + /// The state of the modifier keys + modifiers: ModifiersState, + }, + + /// A unicode character was received. + CharacterReceived(char), +} diff --git a/core/src/lib.rs b/core/src/lib.rs index c2887a0b..6b9e612e 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -15,6 +15,7 @@ #![forbid(unsafe_code)] #![forbid(rust_2018_idioms)] pub mod keyboard; +pub mod mouse; mod align; mod background; diff --git a/core/src/mouse.rs b/core/src/mouse.rs new file mode 100644 index 00000000..25ce6ac3 --- /dev/null +++ b/core/src/mouse.rs @@ -0,0 +1,8 @@ +//! Reuse basic mouse types. +mod button; +mod event; +mod interaction; + +pub use button::Button; +pub use event::{Event, ScrollDelta}; +pub use interaction::Interaction; diff --git a/core/src/mouse/button.rs b/core/src/mouse/button.rs new file mode 100644 index 00000000..aeb8a55d --- /dev/null +++ b/core/src/mouse/button.rs @@ -0,0 +1,15 @@ +/// The button of a mouse. +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub enum Button { + /// The left mouse button. + Left, + + /// The right mouse button. + Right, + + /// The middle (wheel) button. + Middle, + + /// Some other button. + Other(u8), +} diff --git a/core/src/mouse/event.rs b/core/src/mouse/event.rs new file mode 100644 index 00000000..2f07b207 --- /dev/null +++ b/core/src/mouse/event.rs @@ -0,0 +1,57 @@ +use super::Button; + +/// A mouse event. +/// +/// _**Note:** This type is largely incomplete! If you need to track +/// additional events, feel free to [open an issue] and share your use case!_ +/// +/// [open an issue]: https://github.com/hecrj/iced/issues +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Event { + /// The mouse cursor entered the window. + CursorEntered, + + /// The mouse cursor left the window. + CursorLeft, + + /// The mouse cursor was moved + CursorMoved { + /// The X coordinate of the mouse position + x: f32, + + /// The Y coordinate of the mouse position + y: f32, + }, + + /// A mouse button was pressed. + ButtonPressed(Button), + + /// A mouse button was released. + ButtonReleased(Button), + + /// The mouse wheel was scrolled. + WheelScrolled { + /// The scroll movement. + delta: ScrollDelta, + }, +} + +/// A scroll movement. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ScrollDelta { + /// A line-based scroll movement + Lines { + /// The number of horizontal lines scrolled + x: f32, + + /// The number of vertical lines scrolled + y: f32, + }, + /// A pixel-based scroll movement + Pixels { + /// The number of horizontal pixels scrolled + x: f32, + /// The number of vertical pixels scrolled + y: f32, + }, +} diff --git a/core/src/mouse/interaction.rs b/core/src/mouse/interaction.rs new file mode 100644 index 00000000..664147a7 --- /dev/null +++ b/core/src/mouse/interaction.rs @@ -0,0 +1,20 @@ +/// The interaction of a mouse cursor. +#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)] +#[allow(missing_docs)] +pub enum Interaction { + Idle, + Pointer, + Grab, + Text, + Crosshair, + Working, + Grabbing, + ResizingHorizontally, + ResizingVertically, +} + +impl Default for Interaction { + fn default() -> Interaction { + Interaction::Idle + } +} diff --git a/core/src/point.rs b/core/src/point.rs index 2b5ad154..3714aa2f 100644 --- a/core/src/point.rs +++ b/core/src/point.rs @@ -1,7 +1,7 @@ use crate::Vector; /// A 2D point. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct Point { /// The X coordinate. pub x: f32, @@ -67,3 +67,11 @@ impl std::ops::Sub<Vector> for Point { } } } + +impl std::ops::Sub<Point> for Point { + type Output = Vector; + + fn sub(self, point: Point) -> Vector { + Vector::new(self.x - point.x, self.y - point.y) + } +} diff --git a/core/src/rectangle.rs b/core/src/rectangle.rs index aead6e9a..ce80c661 100644 --- a/core/src/rectangle.rs +++ b/core/src/rectangle.rs @@ -1,4 +1,4 @@ -use crate::Point; +use crate::{Point, Size, Vector}; /// A rectangle. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] @@ -17,6 +17,35 @@ pub struct Rectangle<T = f32> { } impl Rectangle<f32> { + /// Creates a new [`Rectangle`] with its top-left corner in the given + /// [`Point`] and with the provided [`Size`]. + /// + /// [`Rectangle`]: struct.Rectangle.html + /// [`Point`]: struct.Point.html + /// [`Size`]: struct.Size.html + pub fn new(top_left: Point, size: Size) -> Self { + Self { + x: top_left.x, + y: top_left.y, + width: size.width, + height: size.height, + } + } + + /// Creates a new [`Rectangle`] with its top-left corner at the origin + /// and with the provided [`Size`]. + /// + /// [`Rectangle`]: struct.Rectangle.html + /// [`Size`]: struct.Size.html + pub fn with_size(size: Size) -> Self { + Self { + x: 0.0, + y: 0.0, + width: size.width, + height: size.height, + } + } + /// Returns the [`Point`] at the center of the [`Rectangle`]. /// /// [`Point`]: struct.Point.html @@ -43,6 +72,21 @@ impl Rectangle<f32> { self.y + self.height / 2.0 } + /// Returns the position of the top left corner of the [`Rectangle`]. + /// + /// [`Rectangle`]: struct.Rectangle.html + pub fn position(&self) -> Point { + Point::new(self.x, self.y) + } + + /// Returns the [`Size`] of the [`Rectangle`]. + /// + /// [`Size`]: struct.Size.html + /// [`Rectangle`]: struct.Rectangle.html + pub fn size(&self) -> Size { + Size::new(self.width, self.height) + } + /// Returns true if the given [`Point`] is contained in the [`Rectangle`]. /// /// [`Point`]: struct.Point.html @@ -81,17 +125,29 @@ impl Rectangle<f32> { None } } + + /// Snaps the [`Rectangle`] to __unsigned__ integer coordinates. + /// + /// [`Rectangle`]: struct.Rectangle.html + pub fn snap(self) -> Rectangle<u32> { + Rectangle { + x: self.x as u32, + y: self.y as u32, + width: self.width.ceil() as u32, + height: self.height.ceil() as u32, + } + } } -impl std::ops::Mul<f32> for Rectangle<u32> { +impl std::ops::Mul<f32> for Rectangle<f32> { type Output = Self; fn mul(self, scale: f32) -> Self { Self { - x: (self.x as f32 * scale).round() as u32, - y: (self.y as f32 * scale).round() as u32, - width: (self.width as f32 * scale).round() as u32, - height: (self.height as f32 * scale).round() as u32, + x: self.x as f32 * scale, + y: self.y as f32 * scale, + width: self.width * scale, + height: self.height * scale, } } } @@ -107,13 +163,17 @@ impl From<Rectangle<u32>> for Rectangle<f32> { } } -impl From<Rectangle<f32>> for Rectangle<u32> { - fn from(rectangle: Rectangle<f32>) -> Rectangle<u32> { +impl<T> std::ops::Add<Vector<T>> for Rectangle<T> +where + T: std::ops::Add<Output = T>, +{ + type Output = Rectangle<T>; + + fn add(self, translation: Vector<T>) -> Self { Rectangle { - x: rectangle.x as u32, - y: rectangle.y as u32, - width: rectangle.width.ceil() as u32, - height: rectangle.height.ceil() as u32, + x: self.x + translation.x, + y: self.y + translation.y, + ..self } } } diff --git a/core/src/size.rs b/core/src/size.rs index 4276f05f..aceb5311 100644 --- a/core/src/size.rs +++ b/core/src/size.rs @@ -2,11 +2,20 @@ use std::f32; /// An amount of space in 2 dimensions. #[derive(Debug, Clone, Copy, PartialEq)] -pub struct Size { +pub struct Size<T = f32> { /// The width. - pub width: f32, + pub width: T, /// The height. - pub height: f32, + pub height: T, +} + +impl<T> Size<T> { + /// Creates a new [`Size`] with the given width and height. + /// + /// [`Size`]: struct.Size.html + pub const fn new(width: T, height: T) -> Self { + Size { width, height } + } } impl Size { @@ -15,17 +24,15 @@ impl Size { /// [`Size`]: struct.Size.html pub const ZERO: Size = Size::new(0., 0.); - /// A [`Size`] with infinite width and height. + /// A [`Size`] with a width and height of 1 unit. /// /// [`Size`]: struct.Size.html - pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY); + pub const UNIT: Size = Size::new(1., 1.); - /// Creates a new [`Size`] with the given width and height. + /// A [`Size`] with infinite width and height. /// /// [`Size`]: struct.Size.html - pub const fn new(width: f32, height: f32) -> Self { - Size { width, height } - } + pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY); /// Increments the [`Size`] to account for the given padding. /// diff --git a/core/src/vector.rs b/core/src/vector.rs index a75053a0..def3f8c0 100644 --- a/core/src/vector.rs +++ b/core/src/vector.rs @@ -43,6 +43,17 @@ where } } +impl<T> std::ops::Mul<T> for Vector<T> +where + T: std::ops::Mul<Output = T> + Copy, +{ + type Output = Self; + + fn mul(self, scale: T) -> Self { + Self::new(self.x * scale, self.y * scale) + } +} + impl<T> Default for Vector<T> where T: Default, |