Create iced_core and iced_native
This commit is contained in:
parent
b83a4b42dd
commit
b9e0f74948
81 changed files with 2576 additions and 2709 deletions
13
core/Cargo.toml
Normal file
13
core/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "iced_core"
|
||||
version = "0.1.0-alpha"
|
||||
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
|
||||
edition = "2018"
|
||||
description = "The essential concepts of Iced"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/hecrj/iced"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
stretch = { version = "0.2", optional = true }
|
||||
47
core/src/align.rs
Normal file
47
core/src/align.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/// Alignment on the cross axis of a container.
|
||||
///
|
||||
/// * On a [`Column`], it describes __horizontal__ alignment.
|
||||
/// * On a [`Row`], it describes __vertical__ alignment.
|
||||
///
|
||||
/// [`Column`]: widget/struct.Column.html
|
||||
/// [`Row`]: widget/struct.Row.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Align {
|
||||
/// Align at the start of the cross axis.
|
||||
Start,
|
||||
|
||||
/// Align at the center of the cross axis.
|
||||
Center,
|
||||
|
||||
/// Align at the end of the cross axis.
|
||||
End,
|
||||
|
||||
/// Stretch over the cross axis.
|
||||
Stretch,
|
||||
}
|
||||
|
||||
#[cfg(feature = "stretch")]
|
||||
#[doc(hidden)]
|
||||
impl From<Align> for stretch::style::AlignItems {
|
||||
fn from(align: Align) -> Self {
|
||||
match align {
|
||||
Align::Start => stretch::style::AlignItems::FlexStart,
|
||||
Align::Center => stretch::style::AlignItems::Center,
|
||||
Align::End => stretch::style::AlignItems::FlexEnd,
|
||||
Align::Stretch => stretch::style::AlignItems::Stretch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "stretch")]
|
||||
#[doc(hidden)]
|
||||
impl From<Align> for stretch::style::AlignSelf {
|
||||
fn from(align: Align) -> Self {
|
||||
match align {
|
||||
Align::Start => stretch::style::AlignSelf::FlexStart,
|
||||
Align::Center => stretch::style::AlignSelf::Center,
|
||||
Align::End => stretch::style::AlignSelf::FlexEnd,
|
||||
Align::Stretch => stretch::style::AlignSelf::Stretch,
|
||||
}
|
||||
}
|
||||
}
|
||||
19
core/src/color.rs
Normal file
19
core/src/color.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/// A color in the sRGB color space.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Color {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
/// The black color.
|
||||
pub const BLACK: Color = Color {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
}
|
||||
44
core/src/justify.rs
Normal file
44
core/src/justify.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/// Distribution on the main axis of a container.
|
||||
///
|
||||
/// * On a [`Column`], it describes __vertical__ distribution.
|
||||
/// * On a [`Row`], it describes __horizontal__ distribution.
|
||||
///
|
||||
/// [`Column`]: widget/struct.Column.html
|
||||
/// [`Row`]: widget/struct.Row.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Justify {
|
||||
/// Place items at the start of the main axis.
|
||||
Start,
|
||||
|
||||
/// Place items at the center of the main axis.
|
||||
Center,
|
||||
|
||||
/// Place items at the end of the main axis.
|
||||
End,
|
||||
|
||||
/// Place items with space between.
|
||||
SpaceBetween,
|
||||
|
||||
/// Place items with space around.
|
||||
SpaceAround,
|
||||
|
||||
/// Place items with evenly distributed space.
|
||||
SpaceEvenly,
|
||||
}
|
||||
|
||||
#[cfg(feature = "stretch")]
|
||||
#[doc(hidden)]
|
||||
impl From<Justify> for stretch::style::JustifyContent {
|
||||
fn from(justify: Justify) -> Self {
|
||||
match justify {
|
||||
Justify::Start => stretch::style::JustifyContent::FlexStart,
|
||||
Justify::Center => stretch::style::JustifyContent::Center,
|
||||
Justify::End => stretch::style::JustifyContent::FlexEnd,
|
||||
Justify::SpaceBetween => {
|
||||
stretch::style::JustifyContent::SpaceBetween
|
||||
}
|
||||
Justify::SpaceAround => stretch::style::JustifyContent::SpaceAround,
|
||||
Justify::SpaceEvenly => stretch::style::JustifyContent::SpaceEvenly,
|
||||
}
|
||||
}
|
||||
}
|
||||
6
core/src/length.rs
Normal file
6
core/src/length.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum Length {
|
||||
Fill,
|
||||
Shrink,
|
||||
Units(u16),
|
||||
}
|
||||
18
core/src/lib.rs
Normal file
18
core/src/lib.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
pub mod widget;
|
||||
|
||||
mod align;
|
||||
mod color;
|
||||
mod justify;
|
||||
mod length;
|
||||
mod point;
|
||||
mod rectangle;
|
||||
mod vector;
|
||||
|
||||
pub use align::Align;
|
||||
pub use color::Color;
|
||||
pub use justify::Justify;
|
||||
pub use length::Length;
|
||||
pub use point::Point;
|
||||
pub use rectangle::Rectangle;
|
||||
pub use vector::Vector;
|
||||
pub use widget::*;
|
||||
31
core/src/point.rs
Normal file
31
core/src/point.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use crate::Vector;
|
||||
|
||||
/// A 2D point.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Point {
|
||||
/// The X coordinate.
|
||||
pub x: f32,
|
||||
|
||||
/// The Y coordinate.
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
/// Creates a new [`Point`] with the given coordinates.
|
||||
///
|
||||
/// [`Point`]: struct.Point.html
|
||||
pub fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<Vector> for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, vector: Vector) -> Self {
|
||||
Self {
|
||||
x: self.x + vector.x,
|
||||
y: self.y + vector.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
30
core/src/rectangle.rs
Normal file
30
core/src/rectangle.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use crate::Point;
|
||||
|
||||
/// A rectangle.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Rectangle<T = f32> {
|
||||
/// X coordinate of the top-left corner.
|
||||
pub x: T,
|
||||
|
||||
/// Y coordinate of the top-left corner.
|
||||
pub y: T,
|
||||
|
||||
/// Width of the rectangle.
|
||||
pub width: T,
|
||||
|
||||
/// Height of the rectangle.
|
||||
pub height: T,
|
||||
}
|
||||
|
||||
impl Rectangle<f32> {
|
||||
/// Returns true if the given [`Point`] is contained in the [`Rectangle`].
|
||||
///
|
||||
/// [`Point`]: struct.Point.html
|
||||
/// [`Rectangle`]: struct.Rectangle.html
|
||||
pub fn contains(&self, point: Point) -> bool {
|
||||
self.x <= point.x
|
||||
&& point.x <= self.x + self.width
|
||||
&& self.y <= point.y
|
||||
&& point.y <= self.y + self.height
|
||||
}
|
||||
}
|
||||
15
core/src/vector.rs
Normal file
15
core/src/vector.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/// A 2D vector.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Vector {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Vector {
|
||||
/// Creates a new [`Vector`] with the given components.
|
||||
///
|
||||
/// [`Vector`]: struct.Vector.html
|
||||
pub fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
27
core/src/widget.rs
Normal file
27
core/src/widget.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
//! Use the essential widgets.
|
||||
//!
|
||||
//! # Re-exports
|
||||
//! For convenience, the contents of this module are available at the root
|
||||
//! module. Therefore, you can directly type:
|
||||
//!
|
||||
//! ```
|
||||
//! use iced_core::{button, Button};
|
||||
//! ```
|
||||
mod column;
|
||||
mod row;
|
||||
|
||||
pub mod button;
|
||||
pub mod checkbox;
|
||||
pub mod image;
|
||||
pub mod radio;
|
||||
pub mod slider;
|
||||
pub mod text;
|
||||
|
||||
pub use button::Button;
|
||||
pub use checkbox::Checkbox;
|
||||
pub use column::Column;
|
||||
pub use image::Image;
|
||||
pub use radio::Radio;
|
||||
pub use row::Row;
|
||||
pub use slider::Slider;
|
||||
pub use text::Text;
|
||||
158
core/src/widget/button.rs
Normal file
158
core/src/widget/button.rs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
//! Allow your users to perform actions by pressing a button.
|
||||
//!
|
||||
//! A [`Button`] has some local [`State`].
|
||||
//!
|
||||
//! [`Button`]: struct.Button.html
|
||||
//! [`State`]: struct.State.html
|
||||
|
||||
use crate::{Align, Length};
|
||||
|
||||
/// A generic widget that produces a message when clicked.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use iced_core::{button, Button};
|
||||
///
|
||||
/// pub enum Message {
|
||||
/// ButtonClicked,
|
||||
/// }
|
||||
///
|
||||
/// let state = &mut button::State::new();
|
||||
///
|
||||
/// Button::new(state, "Click me!")
|
||||
/// .on_press(Message::ButtonClicked);
|
||||
/// ```
|
||||
///
|
||||
/// 
|
||||
pub struct Button<'a, Message> {
|
||||
/// The current state of the button
|
||||
pub state: &'a mut State,
|
||||
|
||||
/// The label of the button
|
||||
pub label: String,
|
||||
|
||||
/// The message to produce when the button is pressed
|
||||
pub on_press: Option<Message>,
|
||||
|
||||
pub class: Class,
|
||||
|
||||
pub width: Length,
|
||||
|
||||
pub align_self: Option<Align>,
|
||||
}
|
||||
|
||||
impl<'a, Message> std::fmt::Debug for Button<'a, Message>
|
||||
where
|
||||
Message: std::fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Button")
|
||||
.field("state", &self.state)
|
||||
.field("label", &self.label)
|
||||
.field("on_press", &self.on_press)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message> Button<'a, Message> {
|
||||
/// Creates a new [`Button`] with some local [`State`] and the given label.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
/// [`State`]: struct.State.html
|
||||
pub fn new(state: &'a mut State, label: &str) -> Self {
|
||||
Button {
|
||||
state,
|
||||
label: String::from(label),
|
||||
on_press: None,
|
||||
class: Class::Primary,
|
||||
width: Length::Shrink,
|
||||
align_self: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Button`].
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the alignment of the [`Button`] itself.
|
||||
///
|
||||
/// This is useful if you want to override the default alignment given by
|
||||
/// the parent container.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
pub fn align_self(mut self, align: Align) -> Self {
|
||||
self.align_self = Some(align);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [`Class`] of the [`Button`].
|
||||
///
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
/// [`Class`]: enum.Class.html
|
||||
pub fn class(mut self, class: Class) -> Self {
|
||||
self.class = class;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the message that will be produced when the [`Button`] is pressed.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
pub fn on_press(mut self, msg: Message) -> Self {
|
||||
self.on_press = Some(msg);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The local state of a [`Button`].
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct State {
|
||||
pub is_pressed: bool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Creates a new [`State`].
|
||||
///
|
||||
/// [`State`]: struct.State.html
|
||||
pub fn new() -> State {
|
||||
State::default()
|
||||
}
|
||||
|
||||
/// Returns whether the associated [`Button`] is currently being pressed or
|
||||
/// not.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
pub fn is_pressed(&self) -> bool {
|
||||
self.is_pressed
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of a [`Button`].
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Class {
|
||||
/// The [`Button`] performs the main action.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
Primary,
|
||||
|
||||
/// The [`Button`] performs an alternative action.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
Secondary,
|
||||
|
||||
/// The [`Button`] performs a productive action.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
Positive,
|
||||
}
|
||||
78
core/src/widget/checkbox.rs
Normal file
78
core/src/widget/checkbox.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! Show toggle controls using checkboxes.
|
||||
use crate::Color;
|
||||
|
||||
/// A box that can be checked.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use iced_core::Checkbox;
|
||||
///
|
||||
/// pub enum Message {
|
||||
/// CheckboxToggled(bool),
|
||||
/// }
|
||||
///
|
||||
/// let is_checked = true;
|
||||
///
|
||||
/// Checkbox::new(is_checked, "Toggle me!", Message::CheckboxToggled);
|
||||
/// ```
|
||||
///
|
||||
/// 
|
||||
pub struct Checkbox<Message> {
|
||||
/// Whether the checkbox is checked or not
|
||||
pub is_checked: bool,
|
||||
|
||||
/// Function to call when checkbox is toggled to produce a __message__.
|
||||
///
|
||||
/// The function should be provided `true` when the checkbox is checked
|
||||
/// and `false` otherwise.
|
||||
pub on_toggle: Box<dyn Fn(bool) -> Message>,
|
||||
|
||||
/// The label of the checkbox
|
||||
pub label: String,
|
||||
|
||||
/// The color of the label
|
||||
pub label_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl<Message> std::fmt::Debug for Checkbox<Message> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Checkbox")
|
||||
.field("is_checked", &self.is_checked)
|
||||
.field("label", &self.label)
|
||||
.field("label_color", &self.label_color)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message> Checkbox<Message> {
|
||||
/// Creates a new [`Checkbox`].
|
||||
///
|
||||
/// It expects:
|
||||
/// * a boolean describing whether the [`Checkbox`] is checked or not
|
||||
/// * the label of the [`Checkbox`]
|
||||
/// * a function that will be called when the [`Checkbox`] is toggled.
|
||||
/// It will receive the new state of the [`Checkbox`] and must produce
|
||||
/// a `Message`.
|
||||
///
|
||||
/// [`Checkbox`]: struct.Checkbox.html
|
||||
pub fn new<F>(is_checked: bool, label: &str, f: F) -> Self
|
||||
where
|
||||
F: 'static + Fn(bool) -> Message,
|
||||
{
|
||||
Checkbox {
|
||||
is_checked,
|
||||
on_toggle: Box::new(f),
|
||||
label: String::from(label),
|
||||
label_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the color of the label of the [`Checkbox`].
|
||||
///
|
||||
/// [`Checkbox`]: struct.Checkbox.html
|
||||
pub fn label_color<C: Into<Color>>(mut self, color: C) -> Self {
|
||||
self.label_color = Some(color.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
147
core/src/widget/column.rs
Normal file
147
core/src/widget/column.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
use crate::{Align, Justify, Length};
|
||||
|
||||
/// A container that distributes its contents vertically.
|
||||
///
|
||||
/// A [`Column`] will try to fill the horizontal space of its container.
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub struct Column<Element> {
|
||||
pub spacing: u16,
|
||||
pub padding: u16,
|
||||
pub width: Length,
|
||||
pub height: Length,
|
||||
pub max_width: Length,
|
||||
pub max_height: Length,
|
||||
pub align_self: Option<Align>,
|
||||
pub align_items: Align,
|
||||
pub justify_content: Justify,
|
||||
pub children: Vec<Element>,
|
||||
}
|
||||
|
||||
impl<Element> Column<Element> {
|
||||
/// Creates an empty [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn new() -> Self {
|
||||
Column {
|
||||
spacing: 0,
|
||||
padding: 0,
|
||||
width: Length::Fill,
|
||||
height: Length::Shrink,
|
||||
max_width: Length::Shrink,
|
||||
max_height: Length::Shrink,
|
||||
align_self: None,
|
||||
align_items: Align::Start,
|
||||
justify_content: Justify::Start,
|
||||
children: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the vertical spacing _between_ elements.
|
||||
///
|
||||
/// Custom margins per element do not exist in Iced. You should use this
|
||||
/// method instead! While less flexible, it helps you keep spacing between
|
||||
/// elements consistent.
|
||||
pub fn spacing(mut self, units: u16) -> Self {
|
||||
self.spacing = units;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the padding of the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn padding(mut self, units: u16) -> Self {
|
||||
self.padding = units;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn height(mut self, height: Length) -> Self {
|
||||
self.height = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum width of the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn max_width(mut self, max_width: Length) -> Self {
|
||||
self.max_width = max_width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum height of the [`Column`] in pixels.
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn max_height(mut self, max_height: Length) -> Self {
|
||||
self.max_height = max_height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the alignment of the [`Column`] itself.
|
||||
///
|
||||
/// This is useful if you want to override the default alignment given by
|
||||
/// the parent container.
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn align_self(mut self, align: Align) -> Self {
|
||||
self.align_self = Some(align);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the horizontal alignment of the contents of the [`Column`] .
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn align_items(mut self, align: Align) -> Self {
|
||||
self.align_items = align;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the vertical distribution strategy for the contents of the
|
||||
/// [`Column`] .
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn justify_content(mut self, justify: Justify) -> Self {
|
||||
self.justify_content = justify;
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an element to the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn push<E>(mut self, child: E) -> Column<Element>
|
||||
where
|
||||
E: Into<Element>,
|
||||
{
|
||||
self.children.push(child.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Element> Default for Column<Element> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Element> std::fmt::Debug for Column<Element>
|
||||
where
|
||||
Element: std::fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// TODO: Complete once stabilized
|
||||
f.debug_struct("Column")
|
||||
.field("spacing", &self.spacing)
|
||||
.field("children", &self.children)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
89
core/src/widget/image.rs
Normal file
89
core/src/widget/image.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
//! Display images in your user interface.
|
||||
|
||||
use crate::{Align, Length, Rectangle};
|
||||
|
||||
/// A frame that displays an image while keeping aspect ratio.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use iced_core::Image;
|
||||
///
|
||||
/// # let my_handle = String::from("some_handle");
|
||||
/// let image = Image::new(my_handle);
|
||||
/// ```
|
||||
pub struct Image<I> {
|
||||
/// The image handle
|
||||
pub handle: I,
|
||||
|
||||
/// The part of the image to show
|
||||
pub clip: Option<Rectangle<u16>>,
|
||||
|
||||
/// The width of the image
|
||||
pub width: Length,
|
||||
|
||||
/// The height of the image
|
||||
pub height: Length,
|
||||
|
||||
pub align_self: Option<Align>,
|
||||
}
|
||||
|
||||
impl<I> std::fmt::Debug for Image<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Image")
|
||||
.field("clip", &self.clip)
|
||||
.field("width", &self.width)
|
||||
.field("height", &self.height)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Image<I> {
|
||||
/// Creates a new [`Image`] with given image handle.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
pub fn new(handle: I) -> Self {
|
||||
Image {
|
||||
handle,
|
||||
clip: None,
|
||||
width: Length::Shrink,
|
||||
height: Length::Shrink,
|
||||
align_self: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the portion of the [`Image`] to draw.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
pub fn clip(mut self, clip: Rectangle<u16>) -> Self {
|
||||
self.clip = Some(clip);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Image`] boundaries.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the [`Image`] boundaries.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
pub fn height(mut self, height: Length) -> Self {
|
||||
self.height = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the alignment of the [`Image`] itself.
|
||||
///
|
||||
/// This is useful if you want to override the default alignment given by
|
||||
/// the parent container.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
pub fn align_self(mut self, align: Align) -> Self {
|
||||
self.align_self = Some(align);
|
||||
self
|
||||
}
|
||||
}
|
||||
88
core/src/widget/radio.rs
Normal file
88
core/src/widget/radio.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
//! Create choices using radio buttons.
|
||||
use crate::Color;
|
||||
|
||||
/// A circular button representing a choice.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use iced_core::Radio;
|
||||
///
|
||||
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
/// pub enum Choice {
|
||||
/// A,
|
||||
/// B,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug, Clone, Copy)]
|
||||
/// pub enum Message {
|
||||
/// RadioSelected(Choice),
|
||||
/// }
|
||||
///
|
||||
/// let selected_choice = Some(Choice::A);
|
||||
///
|
||||
/// Radio::new(Choice::A, "This is A", selected_choice, Message::RadioSelected);
|
||||
///
|
||||
/// Radio::new(Choice::B, "This is B", selected_choice, Message::RadioSelected);
|
||||
/// ```
|
||||
///
|
||||
/// 
|
||||
pub struct Radio<Message> {
|
||||
/// Whether the radio button is selected or not
|
||||
pub is_selected: bool,
|
||||
|
||||
/// The message to produce when the radio button is clicked
|
||||
pub on_click: Message,
|
||||
|
||||
/// The label of the radio button
|
||||
pub label: String,
|
||||
|
||||
/// The color of the label
|
||||
pub label_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl<Message> std::fmt::Debug for Radio<Message>
|
||||
where
|
||||
Message: std::fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Radio")
|
||||
.field("is_selected", &self.is_selected)
|
||||
.field("on_click", &self.on_click)
|
||||
.field("label", &self.label)
|
||||
.field("label_color", &self.label_color)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message> Radio<Message> {
|
||||
/// Creates a new [`Radio`] button.
|
||||
///
|
||||
/// It expects:
|
||||
/// * the value related to the [`Radio`] button
|
||||
/// * the label of the [`Radio`] button
|
||||
/// * the current selected value
|
||||
/// * a function that will be called when the [`Radio`] is selected. It
|
||||
/// receives the value of the radio and must produce a `Message`.
|
||||
///
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
pub fn new<F, V>(value: V, label: &str, selected: Option<V>, f: F) -> Self
|
||||
where
|
||||
V: Eq + Copy,
|
||||
F: 'static + Fn(V) -> Message,
|
||||
{
|
||||
Radio {
|
||||
is_selected: Some(value) == selected,
|
||||
on_click: f(value),
|
||||
label: String::from(label),
|
||||
label_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `Color` of the label of the [`Radio`].
|
||||
///
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
pub fn label_color<C: Into<Color>>(mut self, color: C) -> Self {
|
||||
self.label_color = Some(color.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
142
core/src/widget/row.rs
Normal file
142
core/src/widget/row.rs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use crate::{Align, Justify, Length};
|
||||
|
||||
/// A container that distributes its contents horizontally.
|
||||
///
|
||||
/// A [`Row`] will try to fill the horizontal space of its container.
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub struct Row<Element> {
|
||||
pub spacing: u16,
|
||||
pub padding: u16,
|
||||
pub width: Length,
|
||||
pub height: Length,
|
||||
pub max_width: Length,
|
||||
pub max_height: Length,
|
||||
pub align_self: Option<Align>,
|
||||
pub align_items: Align,
|
||||
pub justify_content: Justify,
|
||||
pub children: Vec<Element>,
|
||||
}
|
||||
|
||||
impl<Element> Row<Element> {
|
||||
/// Creates an empty [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn new() -> Self {
|
||||
Row {
|
||||
spacing: 0,
|
||||
padding: 0,
|
||||
width: Length::Fill,
|
||||
height: Length::Shrink,
|
||||
max_width: Length::Shrink,
|
||||
max_height: Length::Shrink,
|
||||
align_self: None,
|
||||
align_items: Align::Start,
|
||||
justify_content: Justify::Start,
|
||||
children: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the horizontal spacing _between_ elements.
|
||||
///
|
||||
/// Custom margins per element do not exist in Iced. You should use this
|
||||
/// method instead! While less flexible, it helps you keep spacing between
|
||||
/// elements consistent.
|
||||
pub fn spacing(mut self, units: u16) -> Self {
|
||||
self.spacing = units;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the padding of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn padding(mut self, units: u16) -> Self {
|
||||
self.padding = units;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn height(mut self, height: Length) -> Self {
|
||||
self.height = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum width of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn max_width(mut self, max_width: Length) -> Self {
|
||||
self.max_width = max_width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum height of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn max_height(mut self, max_height: Length) -> Self {
|
||||
self.max_height = max_height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the alignment of the [`Row`] itself.
|
||||
///
|
||||
/// This is useful if you want to override the default alignment given by
|
||||
/// the parent container.
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn align_self(mut self, align: Align) -> Self {
|
||||
self.align_self = Some(align);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the vertical alignment of the contents of the [`Row`] .
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn align_items(mut self, align: Align) -> Self {
|
||||
self.align_items = align;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the horizontal distribution strategy for the contents of the
|
||||
/// [`Row`] .
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn justify_content(mut self, justify: Justify) -> Self {
|
||||
self.justify_content = justify;
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an [`Element`] to the [`Row`].
|
||||
///
|
||||
/// [`Element`]: ../struct.Element.html
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn push<E>(mut self, child: E) -> Row<Element>
|
||||
where
|
||||
E: Into<Element>,
|
||||
{
|
||||
self.children.push(child.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Element> std::fmt::Debug for Row<Element>
|
||||
where
|
||||
Element: std::fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// TODO: Complete once stabilized
|
||||
f.debug_struct("Row")
|
||||
.field("spacing", &self.spacing)
|
||||
.field("children", &self.children)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
123
core/src/widget/slider.rs
Normal file
123
core/src/widget/slider.rs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
//! Display an interactive selector of a single value from a range of values.
|
||||
//!
|
||||
//! A [`Slider`] has some local [`State`].
|
||||
//!
|
||||
//! [`Slider`]: struct.Slider.html
|
||||
//! [`State`]: struct.State.html
|
||||
use crate::Length;
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// An horizontal bar and a handle that selects a single value from a range of
|
||||
/// values.
|
||||
///
|
||||
/// A [`Slider`] will try to fill the horizontal space of its container.
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use iced_core::{slider, Slider};
|
||||
///
|
||||
/// pub enum Message {
|
||||
/// SliderChanged(f32),
|
||||
/// }
|
||||
///
|
||||
/// let state = &mut slider::State::new();
|
||||
/// let value = 50.0;
|
||||
///
|
||||
/// Slider::new(state, 0.0..=100.0, value, Message::SliderChanged);
|
||||
/// ```
|
||||
///
|
||||
/// 
|
||||
pub struct Slider<'a, Message> {
|
||||
/// The state of the slider
|
||||
pub state: &'a mut State,
|
||||
|
||||
/// The range of the slider
|
||||
pub range: RangeInclusive<f32>,
|
||||
|
||||
/// The current value of the slider
|
||||
pub value: f32,
|
||||
|
||||
/// The function to produce messages on change
|
||||
pub on_change: Rc<Box<dyn Fn(f32) -> Message>>,
|
||||
|
||||
pub width: Length,
|
||||
}
|
||||
|
||||
impl<'a, Message> std::fmt::Debug for Slider<'a, Message> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Slider")
|
||||
.field("state", &self.state)
|
||||
.field("range", &self.range)
|
||||
.field("value", &self.value)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message> Slider<'a, Message> {
|
||||
/// Creates a new [`Slider`].
|
||||
///
|
||||
/// It expects:
|
||||
/// * the local [`State`] of the [`Slider`]
|
||||
/// * an inclusive range of possible values
|
||||
/// * the current value of the [`Slider`]
|
||||
/// * a function that will be called when the [`Slider`] is dragged.
|
||||
/// It receives the new value of the [`Slider`] and must produce a
|
||||
/// `Message`.
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
/// [`State`]: struct.State.html
|
||||
pub fn new<F>(
|
||||
state: &'a mut State,
|
||||
range: RangeInclusive<f32>,
|
||||
value: f32,
|
||||
on_change: F,
|
||||
) -> Self
|
||||
where
|
||||
F: 'static + Fn(f32) -> Message,
|
||||
{
|
||||
Slider {
|
||||
state,
|
||||
value: value.max(*range.start()).min(*range.end()),
|
||||
range,
|
||||
on_change: Rc::new(Box::new(on_change)),
|
||||
width: Length::Fill,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Slider`].
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The local state of a [`Slider`].
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct State {
|
||||
pub is_dragging: bool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Creates a new [`State`].
|
||||
///
|
||||
/// [`State`]: struct.State.html
|
||||
pub fn new() -> State {
|
||||
State::default()
|
||||
}
|
||||
|
||||
/// Returns whether the associated [`Slider`] is currently being dragged or
|
||||
/// not.
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
pub fn is_dragging(&self) -> bool {
|
||||
self.is_dragging
|
||||
}
|
||||
}
|
||||
119
core/src/widget/text.rs
Normal file
119
core/src/widget/text.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
//! Write some text for your users to read.
|
||||
use crate::{Color, Length};
|
||||
|
||||
/// A paragraph of text.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use iced_core::Text;
|
||||
///
|
||||
/// Text::new("I <3 iced!")
|
||||
/// .size(40);
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Text {
|
||||
pub content: String,
|
||||
pub size: Option<u16>,
|
||||
pub color: Option<Color>,
|
||||
pub width: Length,
|
||||
pub height: Length,
|
||||
pub horizontal_alignment: HorizontalAlignment,
|
||||
pub vertical_alignment: VerticalAlignment,
|
||||
}
|
||||
|
||||
impl Text {
|
||||
/// Create a new fragment of [`Text`] with the given contents.
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
pub fn new(label: &str) -> Self {
|
||||
Text {
|
||||
content: String::from(label),
|
||||
size: None,
|
||||
color: None,
|
||||
width: Length::Fill,
|
||||
height: Length::Shrink,
|
||||
horizontal_alignment: HorizontalAlignment::Left,
|
||||
vertical_alignment: VerticalAlignment::Top,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the size of the [`Text`].
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
pub fn size(mut self, size: u16) -> Self {
|
||||
self.size = Some(size);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `Color` of the [`Text`].
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
pub fn color<C: Into<Color>>(mut self, color: C) -> Self {
|
||||
self.color = Some(color.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Text`] boundaries.
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
pub fn width(mut self, width: Length) -> Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the [`Text`] boundaries.
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
pub fn height(mut self, height: Length) -> Self {
|
||||
self.height = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [`HorizontalAlignment`] of the [`Text`].
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [`HorizontalAlignment`]: enum.HorizontalAlignment.html
|
||||
pub fn horizontal_alignment(
|
||||
mut self,
|
||||
alignment: HorizontalAlignment,
|
||||
) -> Self {
|
||||
self.horizontal_alignment = alignment;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [`VerticalAlignment`] of the [`Text`].
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [`VerticalAlignment`]: enum.VerticalAlignment.html
|
||||
pub fn vertical_alignment(mut self, alignment: VerticalAlignment) -> Self {
|
||||
self.vertical_alignment = alignment;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The horizontal alignment of some resource.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum HorizontalAlignment {
|
||||
/// Align left
|
||||
Left,
|
||||
|
||||
/// Horizontally centered
|
||||
Center,
|
||||
|
||||
/// Align right
|
||||
Right,
|
||||
}
|
||||
|
||||
/// The vertical alignment of some resource.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum VerticalAlignment {
|
||||
/// Align top
|
||||
Top,
|
||||
|
||||
/// Vertically centered
|
||||
Center,
|
||||
|
||||
/// Align bottom
|
||||
Bottom,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue