Merge branch 'iced-rs:master' into viewer_content_fit
This commit is contained in:
commit
f3a1c785b2
65 changed files with 1648 additions and 1380 deletions
32
README.md
32
README.md
|
|
@ -98,8 +98,8 @@ that can be incremented and decremented using two buttons.
|
||||||
We start by modelling the __state__ of our application:
|
We start by modelling the __state__ of our application:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
#[derive(Default)]
|
||||||
struct Counter {
|
struct Counter {
|
||||||
// The counter value
|
|
||||||
value: i32,
|
value: i32,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -110,8 +110,8 @@ the button presses. These interactions are our __messages__:
|
||||||
```rust
|
```rust
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
IncrementPressed,
|
Increment,
|
||||||
DecrementPressed,
|
Decrement,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -126,15 +126,15 @@ impl Counter {
|
||||||
// We use a column: a simple vertical layout
|
// We use a column: a simple vertical layout
|
||||||
column![
|
column![
|
||||||
// The increment button. We tell it to produce an
|
// The increment button. We tell it to produce an
|
||||||
// `IncrementPressed` message when pressed
|
// `Increment` message when pressed
|
||||||
button("+").on_press(Message::IncrementPressed),
|
button("+").on_press(Message::Increment),
|
||||||
|
|
||||||
// We show the value of the counter here
|
// We show the value of the counter here
|
||||||
text(self.value).size(50),
|
text(self.value).size(50),
|
||||||
|
|
||||||
// The decrement button. We tell it to produce a
|
// The decrement button. We tell it to produce a
|
||||||
// `DecrementPressed` message when pressed
|
// `Decrement` message when pressed
|
||||||
button("-").on_press(Message::DecrementPressed),
|
button("-").on_press(Message::Decrement),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,10 +149,10 @@ impl Counter {
|
||||||
|
|
||||||
pub fn update(&mut self, message: Message) {
|
pub fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::IncrementPressed => {
|
Message::Increment => {
|
||||||
self.value += 1;
|
self.value += 1;
|
||||||
}
|
}
|
||||||
Message::DecrementPressed => {
|
Message::Decrement => {
|
||||||
self.value -= 1;
|
self.value -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,15 +160,22 @@ impl Counter {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And that's everything! We just wrote a whole user interface. Iced is now able
|
And that's everything! We just wrote a whole user interface. Let's run it:
|
||||||
to:
|
|
||||||
|
```rust
|
||||||
|
fn main() -> iced::Result {
|
||||||
|
iced::run("A cool counter", Counter::update, Counter::view)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Iced will automatically:
|
||||||
|
|
||||||
1. Take the result of our __view logic__ and layout its widgets.
|
1. Take the result of our __view logic__ and layout its widgets.
|
||||||
1. Process events from our system and produce __messages__ for our
|
1. Process events from our system and produce __messages__ for our
|
||||||
__update logic__.
|
__update logic__.
|
||||||
1. Draw the resulting user interface.
|
1. Draw the resulting user interface.
|
||||||
|
|
||||||
Browse the [documentation] and the [examples] to learn more!
|
Read the [book], the [documentation], and the [examples] to learn more!
|
||||||
|
|
||||||
## Implementation details
|
## Implementation details
|
||||||
|
|
||||||
|
|
@ -208,6 +215,7 @@ come chat to [our Discord server].
|
||||||
|
|
||||||
The development of Iced is sponsored by the [Cryptowatch] team at [Kraken.com]
|
The development of Iced is sponsored by the [Cryptowatch] team at [Kraken.com]
|
||||||
|
|
||||||
|
[book]: https://book.iced.rs/
|
||||||
[documentation]: https://docs.rs/iced/
|
[documentation]: https://docs.rs/iced/
|
||||||
[examples]: https://github.com/iced-rs/iced/tree/master/examples
|
[examples]: https://github.com/iced-rs/iced/tree/master/examples
|
||||||
[Coffee]: https://github.com/hecrj/coffee
|
[Coffee]: https://github.com/hecrj/coffee
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,18 @@ use std::ops::{Add, AddAssign, Div, Mul, RangeInclusive, Sub, SubAssign};
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Degrees(pub f32);
|
pub struct Degrees(pub f32);
|
||||||
|
|
||||||
|
impl PartialEq<f32> for Degrees {
|
||||||
|
fn eq(&self, other: &f32) -> bool {
|
||||||
|
self.0.eq(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd<f32> for Degrees {
|
||||||
|
fn partial_cmp(&self, other: &f32) -> Option<std::cmp::Ordering> {
|
||||||
|
self.0.partial_cmp(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Radians
|
/// Radians
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Radians(pub f32);
|
pub struct Radians(pub f32);
|
||||||
|
|
@ -140,3 +152,15 @@ impl Div for Radians {
|
||||||
Self(self.0 / rhs.0)
|
Self(self.0 / rhs.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<f32> for Radians {
|
||||||
|
fn eq(&self, other: &f32) -> bool {
|
||||||
|
self.0.eq(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd<f32> for Radians {
|
||||||
|
fn partial_cmp(&self, other: &f32) -> Option<std::cmp::Ordering> {
|
||||||
|
self.0.partial_cmp(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,20 +53,20 @@ impl Size {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<[f32; 2]> for Size {
|
impl<T> From<[T; 2]> for Size<T> {
|
||||||
fn from([width, height]: [f32; 2]) -> Self {
|
fn from([width, height]: [T; 2]) -> Self {
|
||||||
Size { width, height }
|
Size { width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<[u16; 2]> for Size {
|
impl<T> From<(T, T)> for Size<T> {
|
||||||
fn from([width, height]: [u16; 2]) -> Self {
|
fn from((width, height): (T, T)) -> Self {
|
||||||
Size::new(width.into(), height.into())
|
Self { width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vector<f32>> for Size {
|
impl<T> From<Vector<T>> for Size<T> {
|
||||||
fn from(vector: Vector<f32>) -> Self {
|
fn from(vector: Vector<T>) -> Self {
|
||||||
Size {
|
Size {
|
||||||
width: vector.x,
|
width: vector.x,
|
||||||
height: vector.y,
|
height: vector.y,
|
||||||
|
|
@ -74,20 +74,23 @@ impl From<Vector<f32>> for Size {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Size> for [f32; 2] {
|
impl<T> From<Size<T>> for [T; 2] {
|
||||||
fn from(size: Size) -> [f32; 2] {
|
fn from(size: Size<T>) -> Self {
|
||||||
[size.width, size.height]
|
[size.width, size.height]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Size> for Vector<f32> {
|
impl<T> From<Size<T>> for Vector<T> {
|
||||||
fn from(size: Size) -> Self {
|
fn from(size: Size<T>) -> Self {
|
||||||
Vector::new(size.width, size.height)
|
Vector::new(size.width, size.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Sub for Size {
|
impl<T> std::ops::Sub for Size<T>
|
||||||
type Output = Size;
|
where
|
||||||
|
T: std::ops::Sub<Output = T>,
|
||||||
|
{
|
||||||
|
type Output = Size<T>;
|
||||||
|
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
Size {
|
Size {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ pub enum Theme {
|
||||||
Nightfly,
|
Nightfly,
|
||||||
/// The built-in Oxocarbon variant.
|
/// The built-in Oxocarbon variant.
|
||||||
Oxocarbon,
|
Oxocarbon,
|
||||||
|
/// The built-in Ferra variant:
|
||||||
|
Ferra,
|
||||||
/// A [`Theme`] that uses a [`Custom`] palette.
|
/// A [`Theme`] that uses a [`Custom`] palette.
|
||||||
Custom(Arc<Custom>),
|
Custom(Arc<Custom>),
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +82,7 @@ impl Theme {
|
||||||
Self::Moonfly,
|
Self::Moonfly,
|
||||||
Self::Nightfly,
|
Self::Nightfly,
|
||||||
Self::Oxocarbon,
|
Self::Oxocarbon,
|
||||||
|
Self::Ferra,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Creates a new custom [`Theme`] from the given [`Palette`].
|
/// Creates a new custom [`Theme`] from the given [`Palette`].
|
||||||
|
|
@ -121,6 +124,7 @@ impl Theme {
|
||||||
Self::Moonfly => Palette::MOONFLY,
|
Self::Moonfly => Palette::MOONFLY,
|
||||||
Self::Nightfly => Palette::NIGHTFLY,
|
Self::Nightfly => Palette::NIGHTFLY,
|
||||||
Self::Oxocarbon => Palette::OXOCARBON,
|
Self::Oxocarbon => Palette::OXOCARBON,
|
||||||
|
Self::Ferra => Palette::FERRA,
|
||||||
Self::Custom(custom) => custom.palette,
|
Self::Custom(custom) => custom.palette,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +155,7 @@ impl Theme {
|
||||||
Self::Moonfly => &palette::EXTENDED_MOONFLY,
|
Self::Moonfly => &palette::EXTENDED_MOONFLY,
|
||||||
Self::Nightfly => &palette::EXTENDED_NIGHTFLY,
|
Self::Nightfly => &palette::EXTENDED_NIGHTFLY,
|
||||||
Self::Oxocarbon => &palette::EXTENDED_OXOCARBON,
|
Self::Oxocarbon => &palette::EXTENDED_OXOCARBON,
|
||||||
|
Self::Ferra => &palette::EXTENDED_FERRA,
|
||||||
Self::Custom(custom) => &custom.extended,
|
Self::Custom(custom) => &custom.extended,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -180,6 +185,7 @@ impl fmt::Display for Theme {
|
||||||
Self::Moonfly => write!(f, "Moonfly"),
|
Self::Moonfly => write!(f, "Moonfly"),
|
||||||
Self::Nightfly => write!(f, "Nightfly"),
|
Self::Nightfly => write!(f, "Nightfly"),
|
||||||
Self::Oxocarbon => write!(f, "Oxocarbon"),
|
Self::Oxocarbon => write!(f, "Oxocarbon"),
|
||||||
|
Self::Ferra => write!(f, "Ferra"),
|
||||||
Self::Custom(custom) => custom.fmt(f),
|
Self::Custom(custom) => custom.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,17 @@ impl Palette {
|
||||||
success: color!(0x00c15a),
|
success: color!(0x00c15a),
|
||||||
danger: color!(0xf62d0f),
|
danger: color!(0xf62d0f),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The built-in [Ferra] variant of a [`Palette`].
|
||||||
|
///
|
||||||
|
/// [Ferra]: https://github.com/casperstorm/ferra
|
||||||
|
pub const FERRA: Self = Self {
|
||||||
|
background: color!(0x2b292d),
|
||||||
|
text: color!(0xfecdb2),
|
||||||
|
primary: color!(0xd1d1e0),
|
||||||
|
success: color!(0xb1b695),
|
||||||
|
danger: color!(0xe06b75),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An extended set of colors generated from a [`Palette`].
|
/// An extended set of colors generated from a [`Palette`].
|
||||||
|
|
@ -379,6 +390,10 @@ pub static EXTENDED_NIGHTFLY: Lazy<Extended> =
|
||||||
pub static EXTENDED_OXOCARBON: Lazy<Extended> =
|
pub static EXTENDED_OXOCARBON: Lazy<Extended> =
|
||||||
Lazy::new(|| Extended::generate(Palette::OXOCARBON));
|
Lazy::new(|| Extended::generate(Palette::OXOCARBON));
|
||||||
|
|
||||||
|
/// The built-in Ferra variant of an [`Extended`] palette.
|
||||||
|
pub static EXTENDED_FERRA: Lazy<Extended> =
|
||||||
|
Lazy::new(|| Extended::generate(Palette::FERRA));
|
||||||
|
|
||||||
impl Extended {
|
impl Extended {
|
||||||
/// Generates an [`Extended`] palette from a simple [`Palette`].
|
/// Generates an [`Extended`] palette from a simple [`Palette`].
|
||||||
pub fn generate(palette: Palette) -> Self {
|
pub fn generate(palette: Palette) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub enum RedrawRequest {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::time::{Duration, Instant};
|
use crate::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ordering() {
|
fn ordering() {
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" fill="none" viewBox="0 0 68 68"><rect width="68" height="68" fill="url(#paint0_linear)" rx="18"/><path fill="url(#paint1_linear)" fill-rule="evenodd" d="M52.2952 16.986L43.0273 26.4088L41.0081 24.4228L50.2761 15L52.2952 16.986ZM43.6175 17.0578L29.7156 31.192L27.6964 29.206L41.5983 15.0718L43.6175 17.0578ZM23.3109 24.9347C25.065 23.1615 26.8188 21.3887 30.4157 17.7317L32.4348 19.7177C28.8353 23.3774 27.0795 25.1523 25.3241 26.9267C23.8744 28.3921 22.425 29.8572 19.9355 32.3857L30.4685 35.1388L39.0223 26.442L41.0414 28.428L32.4876 37.1247L35.4218 47.6353L49.3019 33.7718L51.3033 35.7756L35.1269 51.9327L20.0283 47.7728L15.6165 32.7371L16.2 32.1438C19.7995 28.4842 21.5555 26.7091 23.3109 24.9347ZM32.6721 48.3186L29.7581 37.8804L19.2731 35.1398L22.3017 45.4614L32.6721 48.3186ZM48.3953 29.7021L50.7414 27.3561L48.7387 25.3535L46.3844 27.7078L36.4462 37.812L38.4654 39.7979L48.3953 29.7021Z" clip-rule="evenodd"/><defs><linearGradient id="paint0_linear" x1="34" x2="34" y1="0" y2="68" gradientUnits="userSpaceOnUse"><stop stop-color="#00A3FF"/><stop offset="1" stop-color="#30F"/></linearGradient><linearGradient id="paint1_linear" x1="20.5" x2="60" y1="47.466" y2="6.966" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity=".65"/></linearGradient></defs></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="160" height="180" fill="none" version="1.1" viewBox="35 20 185 195" xmlns="http://www.w3.org/2000/svg"><g filter="url(#filter0_f)"><rect x="59" y="51.001" width="136" height="160" rx="32" fill="url(#paint0_linear)"/></g><rect x="42" y="31.001" width="169.9" height="169.9" rx="49.815" fill="url(#paint1_linear)"/><path d="m182.62 65.747-28.136 28.606-6.13-6.0291 28.136-28.606 6.13 6.0291zm-26.344 0.218-42.204 42.909-6.13-6.029 42.204-42.909 6.13 6.0291zm-61.648 23.913c5.3254-5.3831 10.65-10.765 21.569-21.867l6.13 6.0291c-10.927 11.11-16.258 16.498-21.587 21.885-4.4007 4.4488-8.8009 8.8968-16.359 16.573l31.977 8.358 25.968-26.402 6.13 6.0292-25.968 26.402 8.907 31.908 42.138-42.087 6.076 6.083-49.109 49.05-45.837-12.628-13.394-45.646 1.7714-1.801c10.928-11.111 16.258-16.499 21.588-21.886zm28.419 70.99-8.846-31.689-31.831-8.32 9.1945 31.335 31.482 8.674zm47.734-56.517 7.122-7.1221-6.08-6.0797-7.147 7.1474-30.171 30.674 6.13 6.029 30.146-30.649z" clip-rule="evenodd" fill="url(#paint2_linear)" fill-rule="evenodd"/><defs><filter id="filter0_f" x="55" y="47.001" width="144" height="168" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur" stdDeviation="2"/></filter><linearGradient id="paint0_linear" x1="127" x2="127" y1="51.001" y2="211" gradientUnits="userSpaceOnUse"><stop offset=".052083"/><stop stop-opacity=".08" offset="1"/></linearGradient><linearGradient id="paint1_linear" x1="212" x2="57.5" y1="31.001" y2="189" gradientUnits="userSpaceOnUse"><stop stop-color="#00A3FF" offset="0"/><stop stop-color="#30f" offset="1"/></linearGradient><linearGradient id="paint2_linear" x1="86.098" x2="206.01" y1="158.28" y2="35.327" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient></defs></svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2 KiB |
|
|
@ -1,20 +1,17 @@
|
||||||
use std::{f32::consts::PI, time::Instant};
|
use std::{f32::consts::PI, time::Instant};
|
||||||
|
|
||||||
use iced::executor;
|
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::widget::canvas::{
|
use iced::widget::canvas::{
|
||||||
self, stroke, Cache, Canvas, Geometry, Path, Stroke,
|
self, stroke, Cache, Canvas, Geometry, Path, Stroke,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Element, Length, Point, Rectangle, Renderer, Subscription, Theme};
|
||||||
Application, Command, Element, Length, Point, Rectangle, Renderer,
|
|
||||||
Settings, Subscription, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Arc::run(Settings {
|
iced::program("Arc - Iced", Arc::update, Arc::view)
|
||||||
antialiasing: true,
|
.subscription(Arc::subscription)
|
||||||
..Settings::default()
|
.theme(|_| Theme::Dark)
|
||||||
})
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Arc {
|
struct Arc {
|
||||||
|
|
@ -27,30 +24,9 @@ enum Message {
|
||||||
Tick,
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Arc {
|
impl Arc {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, _: Message) {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Arc {
|
|
||||||
start: Instant::now(),
|
|
||||||
cache: Cache::default(),
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Arc - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, _: Message) -> Command<Message> {
|
|
||||||
self.cache.clear();
|
self.cache.clear();
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
|
@ -60,16 +36,21 @@ impl Application for Arc {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::Dark
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
iced::time::every(std::time::Duration::from_millis(10))
|
iced::time::every(std::time::Duration::from_millis(10))
|
||||||
.map(|_| Message::Tick)
|
.map(|_| Message::Tick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Arc {
|
||||||
|
fn default() -> Self {
|
||||||
|
Arc {
|
||||||
|
start: Instant::now(),
|
||||||
|
cache: Cache::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<Message> canvas::Program<Message> for Arc {
|
impl<Message> canvas::Program<Message> for Arc {
|
||||||
type State = ();
|
type State = ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
//! This example showcases an interactive `Canvas` for drawing Bézier curves.
|
//! This example showcases an interactive `Canvas` for drawing Bézier curves.
|
||||||
use iced::widget::{button, column, text};
|
use iced::widget::{button, column, text};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
use iced::{Alignment, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings {
|
iced::program("Bezier Tool - Iced", Example::update, Example::view)
|
||||||
antialiasing: true,
|
.antialiasing(true)
|
||||||
..Settings::default()
|
.run()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -21,17 +20,7 @@ enum Message {
|
||||||
Clear,
|
Clear,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Example::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Bezier tool - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::AddCurve(curve) => {
|
Message::AddCurve(curve) => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::font::{self, Font};
|
|
||||||
use iced::widget::{checkbox, column, container, row, text};
|
use iced::widget::{checkbox, column, container, row, text};
|
||||||
use iced::{Application, Command, Element, Length, Settings, Theme};
|
use iced::{Element, Font, Length};
|
||||||
|
|
||||||
const ICON_FONT: Font = Font::with_name("icons");
|
const ICON_FONT: Font = Font::with_name("icons");
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::program("Checkbox - Iced", Example::update, Example::view)
|
||||||
|
.font(include_bytes!("../fonts/icons.ttf").as_slice())
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -21,28 +21,10 @@ enum Message {
|
||||||
DefaultToggled(bool),
|
DefaultToggled(bool),
|
||||||
CustomToggled(bool),
|
CustomToggled(bool),
|
||||||
StyledToggled(bool),
|
StyledToggled(bool),
|
||||||
FontLoaded(Result<(), font::Error>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Message = Message;
|
fn update(&mut self, message: Message) {
|
||||||
type Flags = ();
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Theme = Theme;
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self::default(),
|
|
||||||
font::load(include_bytes!("../fonts/icons.ttf").as_slice())
|
|
||||||
.map(Message::FontLoaded),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Checkbox - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::DefaultToggled(default) => {
|
Message::DefaultToggled(default) => {
|
||||||
self.default = default;
|
self.default = default;
|
||||||
|
|
@ -53,10 +35,7 @@ impl Application for Example {
|
||||||
Message::CustomToggled(custom) => {
|
Message::CustomToggled(custom) => {
|
||||||
self.custom = custom;
|
self.custom = custom;
|
||||||
}
|
}
|
||||||
Message::FontLoaded(_) => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
use iced::executor;
|
use iced::alignment;
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::widget::canvas::{stroke, Cache, 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, Command, Element, Length, Point, Rectangle, Renderer,
|
Degrees, Element, Font, Length, Point, Rectangle, Renderer, Subscription,
|
||||||
Settings, Subscription, Theme, Vector,
|
Theme, Vector,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Clock::run(Settings {
|
iced::program("Clock - Iced", Clock::update, Clock::view)
|
||||||
antialiasing: true,
|
.subscription(Clock::subscription)
|
||||||
..Settings::default()
|
.theme(Clock::theme)
|
||||||
})
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Clock {
|
struct Clock {
|
||||||
|
|
@ -24,28 +25,8 @@ enum Message {
|
||||||
Tick(time::OffsetDateTime),
|
Tick(time::OffsetDateTime),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Clock {
|
impl Clock {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, message: Message) {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Clock {
|
|
||||||
now: time::OffsetDateTime::now_local()
|
|
||||||
.unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
|
|
||||||
clock: Cache::default(),
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Clock - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Tick(local_time) => {
|
Message::Tick(local_time) => {
|
||||||
let now = local_time;
|
let now = local_time;
|
||||||
|
|
@ -56,8 +37,6 @@ impl Application for Clock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
|
@ -82,7 +61,18 @@ impl Application for Clock {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
fn theme(&self) -> Theme {
|
||||||
Theme::TokyoNight
|
Theme::ALL[(self.now.unix_timestamp() as usize / 10) % Theme::ALL.len()]
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Clock {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
now: time::OffsetDateTime::now_local()
|
||||||
|
.unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
|
||||||
|
clock: Cache::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +94,7 @@ impl<Message> canvas::Program<Message> for Clock {
|
||||||
let radius = frame.width().min(frame.height()) / 2.0;
|
let radius = frame.width().min(frame.height()) / 2.0;
|
||||||
|
|
||||||
let background = Path::circle(center, radius);
|
let background = Path::circle(center, radius);
|
||||||
frame.fill(&background, palette.primary.weak.color);
|
frame.fill(&background, palette.secondary.strong.color);
|
||||||
|
|
||||||
let short_hand =
|
let short_hand =
|
||||||
Path::line(Point::ORIGIN, Point::new(0.0, -0.5 * radius));
|
Path::line(Point::ORIGIN, Point::new(0.0, -0.5 * radius));
|
||||||
|
|
@ -117,7 +107,7 @@ impl<Message> canvas::Program<Message> for Clock {
|
||||||
let thin_stroke = || -> Stroke {
|
let thin_stroke = || -> Stroke {
|
||||||
Stroke {
|
Stroke {
|
||||||
width,
|
width,
|
||||||
style: stroke::Style::Solid(palette.primary.weak.text),
|
style: stroke::Style::Solid(palette.secondary.strong.text),
|
||||||
line_cap: LineCap::Round,
|
line_cap: LineCap::Round,
|
||||||
..Stroke::default()
|
..Stroke::default()
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +116,7 @@ impl<Message> canvas::Program<Message> for Clock {
|
||||||
let wide_stroke = || -> Stroke {
|
let wide_stroke = || -> Stroke {
|
||||||
Stroke {
|
Stroke {
|
||||||
width: width * 3.0,
|
width: width * 3.0,
|
||||||
style: stroke::Style::Solid(palette.primary.weak.text),
|
style: stroke::Style::Solid(palette.secondary.strong.text),
|
||||||
line_cap: LineCap::Round,
|
line_cap: LineCap::Round,
|
||||||
..Stroke::default()
|
..Stroke::default()
|
||||||
}
|
}
|
||||||
|
|
@ -145,8 +135,31 @@ impl<Message> canvas::Program<Message> for Clock {
|
||||||
});
|
});
|
||||||
|
|
||||||
frame.with_save(|frame| {
|
frame.with_save(|frame| {
|
||||||
frame.rotate(hand_rotation(self.now.second(), 60));
|
let rotation = hand_rotation(self.now.second(), 60);
|
||||||
|
|
||||||
|
frame.rotate(rotation);
|
||||||
frame.stroke(&long_hand, thin_stroke());
|
frame.stroke(&long_hand, thin_stroke());
|
||||||
|
|
||||||
|
let rotate_factor = if rotation < 180.0 { 1.0 } else { -1.0 };
|
||||||
|
|
||||||
|
frame.rotate(Degrees(-90.0 * rotate_factor));
|
||||||
|
frame.fill_text(canvas::Text {
|
||||||
|
content: theme.to_string(),
|
||||||
|
size: (radius / 15.0).into(),
|
||||||
|
position: Point::new(
|
||||||
|
(0.78 * radius) * rotate_factor,
|
||||||
|
-width * 2.0,
|
||||||
|
),
|
||||||
|
color: palette.secondary.strong.text,
|
||||||
|
horizontal_alignment: if rotate_factor > 0.0 {
|
||||||
|
alignment::Horizontal::Right
|
||||||
|
} else {
|
||||||
|
alignment::Horizontal::Left
|
||||||
|
},
|
||||||
|
vertical_alignment: alignment::Vertical::Bottom,
|
||||||
|
font: Font::MONOSPACE,
|
||||||
|
..canvas::Text::default()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -154,8 +167,8 @@ impl<Message> canvas::Program<Message> for Clock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hand_rotation(n: u8, total: u8) -> f32 {
|
fn hand_rotation(n: u8, total: u8) -> Degrees {
|
||||||
let turns = n as f32 / total as f32;
|
let turns = n as f32 / total as f32;
|
||||||
|
|
||||||
2.0 * std::f32::consts::PI * turns
|
Degrees(360.0 * turns)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,23 @@ use iced::mouse;
|
||||||
use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path};
|
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::{
|
||||||
Color, Element, Font, Length, Pixels, Point, Rectangle, Renderer, Sandbox,
|
Color, Element, Font, Length, Pixels, Point, Rectangle, Renderer, Size,
|
||||||
Settings, Size, Vector,
|
Vector,
|
||||||
};
|
|
||||||
use palette::{
|
|
||||||
self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue,
|
|
||||||
};
|
};
|
||||||
|
use palette::{convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
ColorPalette::run(Settings {
|
iced::program(
|
||||||
antialiasing: true,
|
"Color Palette - Iced",
|
||||||
default_font: Font::MONOSPACE,
|
ColorPalette::update,
|
||||||
..Settings::default()
|
ColorPalette::view,
|
||||||
})
|
)
|
||||||
|
.theme(ColorPalette::theme)
|
||||||
|
.default_font(Font::MONOSPACE)
|
||||||
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -41,17 +43,7 @@ pub enum Message {
|
||||||
LchColorChanged(palette::Lch),
|
LchColorChanged(palette::Lch),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for ColorPalette {
|
impl ColorPalette {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Color palette - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
let srgb = match message {
|
let srgb = match message {
|
||||||
Message::RgbColorChanged(rgb) => Rgb::from(rgb),
|
Message::RgbColorChanged(rgb) => Rgb::from(rgb),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
column, combo_box, container, scrollable, text, vertical_space,
|
column, combo_box, container, scrollable, text, vertical_space,
|
||||||
};
|
};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
use iced::{Alignment, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Combo Box - Iced", Example::update, Example::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example {
|
struct Example {
|
||||||
|
|
@ -20,9 +20,7 @@ enum Message {
|
||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
languages: combo_box::State::new(Language::ALL.to_vec()),
|
languages: combo_box::State::new(Language::ALL.to_vec()),
|
||||||
|
|
@ -31,10 +29,6 @@ impl Sandbox for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Combo box - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::Selected(language) => {
|
Message::Selected(language) => {
|
||||||
|
|
@ -83,6 +77,12 @@ impl Sandbox for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Example::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
Danish,
|
Danish,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use iced::widget::container;
|
use iced::widget::container;
|
||||||
use iced::{Element, Length, Sandbox, Settings};
|
use iced::{Element, Length};
|
||||||
|
|
||||||
use numeric_input::numeric_input;
|
use numeric_input::numeric_input;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Component::run(Settings::default())
|
iced::run("Component - Iced", Component::update, Component::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -17,17 +17,7 @@ enum Message {
|
||||||
NumericInputChanged(Option<u32>),
|
NumericInputChanged(Option<u32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Component {
|
impl Component {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Component - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::NumericInputChanged(value) => {
|
Message::NumericInputChanged(value) => {
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,40 @@
|
||||||
use iced::widget::{button, column, text};
|
use iced::widget::{button, column, text, Column};
|
||||||
use iced::{Alignment, Element, Sandbox, Settings};
|
use iced::Alignment;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Counter::run(Settings::default())
|
iced::run("A cool counter", Counter::update, Counter::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct Counter {
|
struct Counter {
|
||||||
value: i32,
|
value: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum Message {
|
enum Message {
|
||||||
IncrementPressed,
|
Increment,
|
||||||
DecrementPressed,
|
Decrement,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Counter {
|
impl Counter {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self { value: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Counter - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::IncrementPressed => {
|
Message::Increment => {
|
||||||
self.value += 1;
|
self.value += 1;
|
||||||
}
|
}
|
||||||
Message::DecrementPressed => {
|
Message::Decrement => {
|
||||||
self.value -= 1;
|
self.value -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Column<Message> {
|
||||||
column![
|
column![
|
||||||
button("Increment").on_press(Message::IncrementPressed),
|
button("Increment").on_press(Message::Increment),
|
||||||
text(self.value).size(50),
|
text(self.value).size(50),
|
||||||
button("Decrement").on_press(Message::DecrementPressed)
|
button("Decrement").on_press(Message::Decrement)
|
||||||
]
|
]
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,12 +82,10 @@ mod quad {
|
||||||
}
|
}
|
||||||
|
|
||||||
use iced::widget::{column, container, slider, text};
|
use iced::widget::{column, container, slider, text};
|
||||||
use iced::{
|
use iced::{Alignment, Color, Element, Length, Shadow, Vector};
|
||||||
Alignment, Color, Element, Length, Sandbox, Settings, Shadow, Vector,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Custom Quad - Iced", Example::update, Example::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example {
|
struct Example {
|
||||||
|
|
@ -109,9 +107,7 @@ enum Message {
|
||||||
ShadowBlurRadiusChanged(f32),
|
ShadowBlurRadiusChanged(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
radius: [50.0; 4],
|
radius: [50.0; 4],
|
||||||
|
|
@ -124,10 +120,6 @@ impl Sandbox for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Custom widget - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
let [tl, tr, br, bl] = self.radius;
|
let [tl, tr, br, bl] = self.radius;
|
||||||
match message {
|
match message {
|
||||||
|
|
@ -203,3 +195,9 @@ impl Sandbox for Example {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,16 @@ mod scene;
|
||||||
|
|
||||||
use scene::Scene;
|
use scene::Scene;
|
||||||
|
|
||||||
use iced::executor;
|
|
||||||
use iced::time::Instant;
|
use iced::time::Instant;
|
||||||
use iced::widget::shader::wgpu;
|
use iced::widget::shader::wgpu;
|
||||||
use iced::widget::{checkbox, column, container, row, shader, slider, text};
|
use iced::widget::{checkbox, column, container, row, shader, slider, text};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{Alignment, Color, Element, Length, Subscription};
|
||||||
Alignment, Application, Color, Command, Element, Length, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() -> iced::Result {
|
fn main() -> iced::Result {
|
||||||
IcedCubes::run(iced::Settings::default())
|
iced::program("Custom Shader - Iced", IcedCubes::update, IcedCubes::view)
|
||||||
|
.subscription(IcedCubes::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IcedCubes {
|
struct IcedCubes {
|
||||||
|
|
@ -30,27 +28,15 @@ enum Message {
|
||||||
LightColorChanged(Color),
|
LightColorChanged(Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for IcedCubes {
|
impl IcedCubes {
|
||||||
type Executor = executor::Default;
|
fn new() -> Self {
|
||||||
type Message = Message;
|
Self {
|
||||||
type Theme = Theme;
|
start: Instant::now(),
|
||||||
type Flags = ();
|
scene: Scene::new(),
|
||||||
|
}
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
start: Instant::now(),
|
|
||||||
scene: Scene::new(),
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn update(&mut self, message: Message) {
|
||||||
"Iced Cubes".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::CubeAmountChanged(amount) => {
|
Message::CubeAmountChanged(amount) => {
|
||||||
self.scene.change_amount(amount);
|
self.scene.change_amount(amount);
|
||||||
|
|
@ -68,11 +54,9 @@ impl Application for IcedCubes {
|
||||||
self.scene.light_color = color;
|
self.scene.light_color = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, Self::Message> {
|
fn view(&self) -> Element<'_, Message> {
|
||||||
let top_controls = row![
|
let top_controls = row![
|
||||||
control(
|
control(
|
||||||
"Amount",
|
"Amount",
|
||||||
|
|
@ -147,11 +131,17 @@ impl Application for IcedCubes {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
window::frames().map(Message::Tick)
|
window::frames().map(Message::Tick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for IcedCubes {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn control<'a>(
|
fn control<'a>(
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
control: impl Into<Element<'a, Message>>,
|
control: impl Into<Element<'a, Message>>,
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,10 @@ mod circle {
|
||||||
|
|
||||||
use circle::circle;
|
use circle::circle;
|
||||||
use iced::widget::{column, container, slider, text};
|
use iced::widget::{column, container, slider, text};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
use iced::{Alignment, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Custom Widget - Iced", Example::update, Example::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example {
|
struct Example {
|
||||||
|
|
@ -98,17 +98,11 @@ enum Message {
|
||||||
RadiusChanged(f32),
|
RadiusChanged(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Example { radius: 50.0 }
|
Example { radius: 50.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Custom widget - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::RadiusChanged(radius) => {
|
Message::RadiusChanged(radius) => {
|
||||||
|
|
@ -136,3 +130,9 @@ impl Sandbox for Example {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{button, column, container, progress_bar, text, Column};
|
|
||||||
use iced::{
|
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod download;
|
mod download;
|
||||||
|
|
||||||
|
use iced::widget::{button, column, container, progress_bar, text, Column};
|
||||||
|
use iced::{Alignment, Element, Length, Subscription};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::program("Download Progress - Iced", Example::update, Example::view)
|
||||||
|
.subscription(Example::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -24,27 +22,15 @@ pub enum Message {
|
||||||
DownloadProgressed((usize, download::Progress)),
|
DownloadProgressed((usize, download::Progress)),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
type Theme = Theme;
|
Self {
|
||||||
type Executor = executor::Default;
|
downloads: vec![Download::new(0)],
|
||||||
type Flags = ();
|
last_id: 0,
|
||||||
|
}
|
||||||
fn new(_flags: ()) -> (Example, Command<Message>) {
|
|
||||||
(
|
|
||||||
Example {
|
|
||||||
downloads: vec![Download::new(0)],
|
|
||||||
last_id: 0,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn update(&mut self, message: Message) {
|
||||||
String::from("Download progress - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Add => {
|
Message::Add => {
|
||||||
self.last_id += 1;
|
self.last_id += 1;
|
||||||
|
|
@ -63,9 +49,7 @@ impl Application for Example {
|
||||||
download.progress(progress);
|
download.progress(progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
@ -93,6 +77,12 @@ impl Application for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Download {
|
struct Download {
|
||||||
id: usize,
|
id: usize,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::highlighter::{self, Highlighter};
|
use iced::highlighter::{self, Highlighter};
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, horizontal_space, pick_list, row, text,
|
button, column, container, horizontal_space, pick_list, row, text,
|
||||||
text_editor, tooltip,
|
text_editor, tooltip,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Alignment, Command, Element, Font, Length, Subscription, Theme};
|
||||||
Alignment, Application, Command, Element, Font, Length, Settings,
|
|
||||||
Subscription, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::ffi;
|
use std::ffi;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
@ -16,11 +12,13 @@ use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Editor::run(Settings {
|
iced::program("Editor - Iced", Editor::update, Editor::view)
|
||||||
fonts: vec![include_bytes!("../fonts/icons.ttf").as_slice().into()],
|
.load(Editor::load)
|
||||||
default_font: Font::MONOSPACE,
|
.subscription(Editor::subscription)
|
||||||
..Settings::default()
|
.theme(Editor::theme)
|
||||||
})
|
.font(include_bytes!("../fonts/icons.ttf").as_slice())
|
||||||
|
.default_font(Font::MONOSPACE)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Editor {
|
struct Editor {
|
||||||
|
|
@ -42,27 +40,22 @@ enum Message {
|
||||||
FileSaved(Result<PathBuf, Error>),
|
FileSaved(Result<PathBuf, Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Editor {
|
impl Editor {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
type Theme = Theme;
|
Self {
|
||||||
type Executor = executor::Default;
|
file: None,
|
||||||
type Flags = ();
|
content: text_editor::Content::new(),
|
||||||
|
theme: highlighter::Theme::SolarizedDark,
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
is_loading: true,
|
||||||
(
|
is_dirty: false,
|
||||||
Self {
|
}
|
||||||
file: None,
|
|
||||||
content: text_editor::Content::new(),
|
|
||||||
theme: highlighter::Theme::SolarizedDark,
|
|
||||||
is_loading: true,
|
|
||||||
is_dirty: false,
|
|
||||||
},
|
|
||||||
Command::perform(load_file(default_file()), Message::FileOpened),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn load() -> Command<Message> {
|
||||||
String::from("Editor - Iced")
|
Command::perform(
|
||||||
|
load_file(format!("{}/src/main.rs", env!("CARGO_MANIFEST_DIR"))),
|
||||||
|
Message::FileOpened,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
|
|
@ -221,16 +214,18 @@ impl Application for Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Editor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
DialogClosed,
|
DialogClosed,
|
||||||
IoError(io::ErrorKind),
|
IoError(io::ErrorKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_file() -> PathBuf {
|
|
||||||
PathBuf::from(format!("{}/src/main.rs", env!("CARGO_MANIFEST_DIR")))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn open_file() -> Result<(PathBuf, Arc<String>), Error> {
|
async fn open_file() -> Result<(PathBuf, Arc<String>), Error> {
|
||||||
let picked_file = rfd::AsyncFileDialog::new()
|
let picked_file = rfd::AsyncFileDialog::new()
|
||||||
.set_title("Open a text file...")
|
.set_title("Open a text file...")
|
||||||
|
|
@ -238,10 +233,14 @@ async fn open_file() -> Result<(PathBuf, Arc<String>), Error> {
|
||||||
.await
|
.await
|
||||||
.ok_or(Error::DialogClosed)?;
|
.ok_or(Error::DialogClosed)?;
|
||||||
|
|
||||||
load_file(picked_file.path().to_owned()).await
|
load_file(picked_file).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_file(path: PathBuf) -> Result<(PathBuf, Arc<String>), Error> {
|
async fn load_file(
|
||||||
|
path: impl Into<PathBuf>,
|
||||||
|
) -> Result<(PathBuf, Arc<String>), Error> {
|
||||||
|
let path = path.into();
|
||||||
|
|
||||||
let contents = tokio::fs::read_to_string(&path)
|
let contents = tokio::fs::read_to_string(&path)
|
||||||
.await
|
.await
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,14 @@
|
||||||
use iced::alignment;
|
use iced::alignment;
|
||||||
use iced::event::{self, Event};
|
use iced::event::{self, Event};
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{button, checkbox, container, text, Column};
|
use iced::widget::{button, checkbox, container, text, Column};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{Alignment, Command, Element, Length, Subscription};
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Events::run(Settings {
|
iced::program("Events - Iced", Events::update, Events::view)
|
||||||
window: window::Settings {
|
.subscription(Events::subscription)
|
||||||
exit_on_close_request: false,
|
.exit_on_close_request(false)
|
||||||
..window::Settings::default()
|
.run()
|
||||||
},
|
|
||||||
..Settings::default()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -31,20 +24,7 @@ enum Message {
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Events {
|
impl Events {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Events, Command<Message>) {
|
|
||||||
(Events::default(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Events - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::EventOccurred(event) if self.enabled => {
|
Message::EventOccurred(event) if self.enabled => {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{button, column, container};
|
use iced::widget::{button, column, container};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{Alignment, Application, Command, Element, Length, Settings, Theme};
|
use iced::{Alignment, Command, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Exit::run(Settings::default())
|
iced::program("Exit - Iced", Exit::update, Exit::view).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -18,20 +17,7 @@ enum Message {
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Exit {
|
impl Exit {
|
||||||
type Executor = executor::Default;
|
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(Self::default(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Exit - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Confirm => window::close(window::Id::MAIN),
|
Message::Confirm => window::close(window::Id::MAIN),
|
||||||
|
|
|
||||||
|
|
@ -5,32 +5,24 @@ mod preset;
|
||||||
use grid::Grid;
|
use grid::Grid;
|
||||||
use preset::Preset;
|
use preset::Preset;
|
||||||
|
|
||||||
use iced::executor;
|
|
||||||
use iced::time;
|
use iced::time;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, checkbox, column, container, pick_list, row, slider, text,
|
button, checkbox, column, container, pick_list, row, slider, text,
|
||||||
};
|
};
|
||||||
use iced::window;
|
use iced::{Alignment, Command, Element, Length, Subscription, Theme};
|
||||||
use iced::{
|
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
GameOfLife::run(Settings {
|
iced::program("Game of Life - Iced", GameOfLife::update, GameOfLife::view)
|
||||||
antialiasing: true,
|
.subscription(GameOfLife::subscription)
|
||||||
window: window::Settings {
|
.theme(|_| Theme::Dark)
|
||||||
position: window::Position::Centered,
|
.antialiasing(true)
|
||||||
..window::Settings::default()
|
.centered()
|
||||||
},
|
.run()
|
||||||
..Settings::default()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct GameOfLife {
|
struct GameOfLife {
|
||||||
grid: Grid,
|
grid: Grid,
|
||||||
is_playing: bool,
|
is_playing: bool,
|
||||||
|
|
@ -52,24 +44,16 @@ enum Message {
|
||||||
PresetPicked(Preset),
|
PresetPicked(Preset),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for GameOfLife {
|
impl GameOfLife {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
type Theme = Theme;
|
Self {
|
||||||
type Executor = executor::Default;
|
grid: Grid::default(),
|
||||||
type Flags = ();
|
is_playing: false,
|
||||||
|
queued_ticks: 0,
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
speed: 5,
|
||||||
(
|
next_speed: None,
|
||||||
Self {
|
version: 0,
|
||||||
speed: 5,
|
}
|
||||||
..Self::default()
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Game of Life - Iced")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
|
|
@ -154,9 +138,11 @@ impl Application for GameOfLife {
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
impl Default for GameOfLife {
|
||||||
Theme::Dark
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,51 +147,35 @@ mod rainbow {
|
||||||
}
|
}
|
||||||
|
|
||||||
use iced::widget::{column, container, scrollable};
|
use iced::widget::{column, container, scrollable};
|
||||||
use iced::{Element, Length, Sandbox, Settings};
|
use iced::{Element, Length};
|
||||||
use rainbow::rainbow;
|
use rainbow::rainbow;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Custom 2D Geometry - Iced", |_: &mut _, _| {}, view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example;
|
fn view(_state: &()) -> Element<'_, ()> {
|
||||||
|
let content = column![
|
||||||
impl Sandbox for Example {
|
rainbow(),
|
||||||
type Message = ();
|
"In this example we draw a custom widget Rainbow, using \
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Custom 2D geometry - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, _: ()) {}
|
|
||||||
|
|
||||||
fn view(&self) -> Element<()> {
|
|
||||||
let content = column![
|
|
||||||
rainbow(),
|
|
||||||
"In this example we draw a custom widget Rainbow, using \
|
|
||||||
the Mesh2D primitive. This primitive supplies a list of \
|
the Mesh2D primitive. This primitive supplies a list of \
|
||||||
triangles, expressed as vertices and indices.",
|
triangles, expressed as vertices and indices.",
|
||||||
"Move your cursor over it, and see the center vertex \
|
"Move your cursor over it, and see the center vertex \
|
||||||
follow you!",
|
follow you!",
|
||||||
"Every Vertex2D defines its own color. You could use the \
|
"Every Vertex2D defines its own color. You could use the \
|
||||||
Mesh2D primitive to render virtually any two-dimensional \
|
Mesh2D primitive to render virtually any two-dimensional \
|
||||||
geometry for your widget.",
|
geometry for your widget.",
|
||||||
]
|
]
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.spacing(20)
|
.spacing(20)
|
||||||
.max_width(500);
|
.max_width(500);
|
||||||
|
|
||||||
let scrollable =
|
let scrollable =
|
||||||
scrollable(container(content).width(Length::Fill).center_x());
|
scrollable(container(content).width(Length::Fill).center_x());
|
||||||
|
|
||||||
container(scrollable)
|
container(scrollable)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.center_y()
|
.center_y()
|
||||||
.into()
|
.into()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,17 @@
|
||||||
use iced::application;
|
use iced::gradient;
|
||||||
|
use iced::program;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
checkbox, column, container, horizontal_space, row, slider, text,
|
checkbox, column, container, horizontal_space, row, slider, text,
|
||||||
};
|
};
|
||||||
use iced::{gradient, window};
|
use iced::{Alignment, Color, Element, Length, Radians, Theme};
|
||||||
use iced::{
|
|
||||||
Alignment, Color, Element, Length, Radians, Sandbox, Settings, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Gradient::run(Settings {
|
iced::program("Gradient - Iced", Gradient::update, Gradient::view)
|
||||||
window: window::Settings {
|
.style(Gradient::style)
|
||||||
transparent: true,
|
.transparent(true)
|
||||||
..Default::default()
|
.run()
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
@ -35,9 +30,7 @@ enum Message {
|
||||||
TransparentToggled(bool),
|
TransparentToggled(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Gradient {
|
impl Gradient {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: Color::WHITE,
|
start: Color::WHITE,
|
||||||
|
|
@ -47,10 +40,6 @@ impl Sandbox for Gradient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Gradient")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::StartChanged(color) => self.start = color,
|
Message::StartChanged(color) => self.start = color,
|
||||||
|
|
@ -106,18 +95,26 @@ impl Sandbox for Gradient {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self, theme: &Theme) -> application::Appearance {
|
fn style(&self, theme: &Theme) -> program::Appearance {
|
||||||
|
use program::DefaultStyle;
|
||||||
|
|
||||||
if self.transparent {
|
if self.transparent {
|
||||||
application::Appearance {
|
program::Appearance {
|
||||||
background_color: Color::TRANSPARENT,
|
background_color: Color::TRANSPARENT,
|
||||||
text_color: theme.palette().text,
|
text_color: theme.palette().text,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
application::default(theme)
|
Theme::default_style(theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Gradient {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn color_picker(label: &str, color: Color) -> Element<'_, Color> {
|
fn color_picker(label: &str, color: Color) -> Element<'_, Color> {
|
||||||
row![
|
row![
|
||||||
text(label).width(64),
|
text(label).width(64),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
|
|
@ -6,15 +5,18 @@ use iced::widget::{
|
||||||
row, scrollable, text,
|
row, scrollable, text,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{
|
||||||
color, Alignment, Application, Command, Element, Font, Length, Point,
|
color, Alignment, Element, Font, Length, Point, Rectangle, Renderer,
|
||||||
Rectangle, Renderer, Settings, Subscription, Theme,
|
Subscription, Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Layout::run(Settings::default())
|
iced::program(Layout::title, Layout::update, Layout::view)
|
||||||
|
.subscription(Layout::subscription)
|
||||||
|
.theme(Layout::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct Layout {
|
struct Layout {
|
||||||
example: Example,
|
example: Example,
|
||||||
explain: bool,
|
explain: bool,
|
||||||
|
|
@ -29,28 +31,12 @@ enum Message {
|
||||||
ThemeSelected(Theme),
|
ThemeSelected(Theme),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Layout {
|
impl Layout {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
example: Example::default(),
|
|
||||||
explain: false,
|
|
||||||
theme: Theme::Light,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
format!("{} - Layout - Iced", self.example.title)
|
format!("{} - Layout - Iced", self.example.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) -> Command<Message> {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::Next => {
|
Message::Next => {
|
||||||
self.example = self.example.next();
|
self.example = self.example.next();
|
||||||
|
|
@ -65,8 +51,6 @@ impl Application for Layout {
|
||||||
self.theme = theme;
|
self.theme = theme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ use iced::widget::{
|
||||||
button, column, horizontal_space, lazy, pick_list, row, scrollable, text,
|
button, column, horizontal_space, lazy, pick_list, row, scrollable, text,
|
||||||
text_input,
|
text_input,
|
||||||
};
|
};
|
||||||
use iced::{Element, Length, Sandbox, Settings};
|
use iced::{Element, Length};
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
App::run(Settings::default())
|
iced::run("Lazy - Iced", App::update, App::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
|
|
@ -120,17 +120,7 @@ enum Message {
|
||||||
ItemColorChanged(Item, Color),
|
ItemColorChanged(Item, Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for App {
|
impl App {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Lazy - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::InputChanged(input) => {
|
Message::InputChanged(input) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{column, container, row, slider, text};
|
use iced::widget::{column, container, row, slider, text};
|
||||||
use iced::{Application, Command, Element, Length, Settings, Theme};
|
use iced::{Element, Length};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|
@ -12,51 +11,31 @@ use circular::Circular;
|
||||||
use linear::Linear;
|
use linear::Linear;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
LoadingSpinners::run(Settings {
|
iced::program(
|
||||||
antialiasing: true,
|
"Loading Spinners - Iced",
|
||||||
..Default::default()
|
LoadingSpinners::update,
|
||||||
})
|
LoadingSpinners::view,
|
||||||
|
)
|
||||||
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoadingSpinners {
|
struct LoadingSpinners {
|
||||||
cycle_duration: f32,
|
cycle_duration: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LoadingSpinners {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
cycle_duration: 2.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum Message {
|
enum Message {
|
||||||
CycleDurationChanged(f32),
|
CycleDurationChanged(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for LoadingSpinners {
|
impl LoadingSpinners {
|
||||||
type Message = Message;
|
fn update(&mut self, message: Message) {
|
||||||
type Flags = ();
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Theme = Theme;
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
|
||||||
(Self::default(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Loading Spinners - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::CycleDurationChanged(duration) => {
|
Message::CycleDurationChanged(duration) => {
|
||||||
self.cycle_duration = duration;
|
self.cycle_duration = duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
|
@ -115,3 +94,11 @@ impl Application for LoadingSpinners {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for LoadingSpinners {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
cycle_duration: 2.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,30 @@
|
||||||
use iced::widget::{button, column, container, text};
|
use iced::widget::{button, column, container, text};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
use iced::{Alignment, Element, Length};
|
||||||
|
|
||||||
use loupe::loupe;
|
use loupe::loupe;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Counter::run(Settings::default())
|
iced::run("Loupe - Iced", Loupe::update, Loupe::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Counter {
|
#[derive(Default)]
|
||||||
value: i32,
|
struct Loupe {
|
||||||
|
value: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum Message {
|
enum Message {
|
||||||
IncrementPressed,
|
Increment,
|
||||||
DecrementPressed,
|
Decrement,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Counter {
|
impl Loupe {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self { value: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Counter - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::IncrementPressed => {
|
Message::Increment => {
|
||||||
self.value += 1;
|
self.value += 1;
|
||||||
}
|
}
|
||||||
Message::DecrementPressed => {
|
Message::Decrement => {
|
||||||
self.value -= 1;
|
self.value -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -43,9 +34,9 @@ impl Sandbox for Counter {
|
||||||
container(loupe(
|
container(loupe(
|
||||||
3.0,
|
3.0,
|
||||||
column![
|
column![
|
||||||
button("Increment").on_press(Message::IncrementPressed),
|
button("Increment").on_press(Message::Increment),
|
||||||
text(self.value).size(50),
|
text(self.value).size(50),
|
||||||
button("Decrement").on_press(Message::DecrementPressed)
|
button("Decrement").on_press(Message::Decrement)
|
||||||
]
|
]
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.align_items(Alignment::Center),
|
.align_items(Alignment::Center),
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
use iced::event::{self, Event};
|
use iced::event::{self, Event};
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::keyboard::key;
|
use iced::keyboard::key;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
self, button, column, container, horizontal_space, pick_list, row, text,
|
self, button, column, container, horizontal_space, pick_list, row, text,
|
||||||
text_input,
|
text_input,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Alignment, Command, Element, Length, Subscription};
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
};
|
|
||||||
|
|
||||||
use modal::Modal;
|
use modal::Modal;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
App::run(Settings::default())
|
iced::program("Modal - Iced", App::update, App::view)
|
||||||
|
.subscription(App::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -36,21 +35,8 @@ enum Message {
|
||||||
Event(Event),
|
Event(Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for App {
|
impl App {
|
||||||
type Executor = executor::Default;
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
type Message = Message;
|
|
||||||
type Theme = iced::Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(App::default(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Modal - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
|
||||||
event::listen().map(Message::Event)
|
event::listen().map(Message::Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,101 +2,58 @@
|
||||||
//! 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::mouse;
|
||||||
|
use iced::touch;
|
||||||
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, Geometry};
|
use iced::widget::canvas::{self, Canvas, Geometry};
|
||||||
use iced::{
|
use iced::{Color, Element, Length, Point, Rectangle, Renderer, Theme};
|
||||||
executor, touch, window, Application, Color, Command, Element, Length,
|
|
||||||
Point, Rectangle, Renderer, Settings, Subscription, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Multitouch::run(Settings {
|
iced::program("Multitouch - Iced", Multitouch::update, Multitouch::view)
|
||||||
antialiasing: true,
|
.antialiasing(true)
|
||||||
window: window::Settings {
|
.centered()
|
||||||
position: window::Position::Centered,
|
.run()
|
||||||
..window::Settings::default()
|
|
||||||
},
|
|
||||||
..Settings::default()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct Multitouch {
|
struct Multitouch {
|
||||||
state: State,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct State {
|
|
||||||
cache: canvas::Cache,
|
cache: canvas::Cache,
|
||||||
fingers: HashMap<touch::Finger, Point>,
|
fingers: HashMap<touch::Finger, Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
cache: canvas::Cache::new(),
|
|
||||||
fingers: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Message {
|
enum Message {
|
||||||
FingerPressed { id: touch::Finger, position: Point },
|
FingerPressed { id: touch::Finger, position: Point },
|
||||||
FingerLifted { id: touch::Finger },
|
FingerLifted { id: touch::Finger },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Multitouch {
|
impl Multitouch {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, message: Message) {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Multitouch {
|
|
||||||
state: State::new(),
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Multitouch - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::FingerPressed { id, position } => {
|
Message::FingerPressed { id, position } => {
|
||||||
self.state.fingers.insert(id, position);
|
self.fingers.insert(id, position);
|
||||||
self.state.cache.clear();
|
self.cache.clear();
|
||||||
}
|
}
|
||||||
Message::FingerLifted { id } => {
|
Message::FingerLifted { id } => {
|
||||||
self.state.fingers.remove(&id);
|
self.fingers.remove(&id);
|
||||||
self.state.cache.clear();
|
self.cache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
|
||||||
Subscription::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
Canvas::new(&self.state)
|
Canvas::new(self)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl canvas::Program<Message> for State {
|
impl canvas::Program<Message> for Multitouch {
|
||||||
type State = ();
|
type State = ();
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
use iced::alignment::{self, Alignment};
|
use iced::alignment::{self, Alignment};
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::widget::pane_grid::{self, PaneGrid};
|
use iced::widget::pane_grid::{self, PaneGrid};
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, responsive, row, scrollable, text,
|
button, column, container, responsive, row, scrollable, text,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Color, Element, Length, Size, Subscription};
|
||||||
Application, Color, Command, Element, Length, Settings, Size, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::program("Pane Grid - Iced", Example::update, Example::view)
|
||||||
|
.subscription(Example::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example {
|
struct Example {
|
||||||
|
|
@ -35,30 +33,18 @@ enum Message {
|
||||||
CloseFocused,
|
CloseFocused,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
let (panes, _) = pane_grid::State::new(Pane::new(0));
|
let (panes, _) = pane_grid::State::new(Pane::new(0));
|
||||||
|
|
||||||
(
|
Example {
|
||||||
Example {
|
panes,
|
||||||
panes,
|
panes_created: 1,
|
||||||
panes_created: 1,
|
focus: None,
|
||||||
focus: None,
|
}
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn update(&mut self, message: Message) {
|
||||||
String::from("Pane grid - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Split(axis, pane) => {
|
Message::Split(axis, pane) => {
|
||||||
let result =
|
let result =
|
||||||
|
|
@ -132,8 +118,6 @@ impl Application for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
@ -209,6 +193,12 @@ impl Application for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Example::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const PANE_ID_COLOR_UNFOCUSED: Color = Color::from_rgb(
|
const PANE_ID_COLOR_UNFOCUSED: Color = Color::from_rgb(
|
||||||
0xFF as f32 / 255.0,
|
0xFF as f32 / 255.0,
|
||||||
0xC7 as f32 / 255.0,
|
0xC7 as f32 / 255.0,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use iced::widget::{column, pick_list, scrollable, vertical_space};
|
use iced::widget::{column, pick_list, scrollable, vertical_space};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
use iced::{Alignment, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Pick List - Iced", Example::update, Example::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -15,17 +15,7 @@ enum Message {
|
||||||
LanguageSelected(Language),
|
LanguageSelected(Language),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Pick list - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::LanguageSelected(language) => {
|
Message::LanguageSelected(language) => {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,20 @@
|
||||||
use iced::futures;
|
use iced::futures;
|
||||||
use iced::widget::{self, column, container, image, row, text};
|
use iced::widget::{self, column, container, image, row, text};
|
||||||
use iced::{Alignment, Application, Command, Element, Length, Settings, Theme};
|
use iced::{Alignment, Command, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Pokedex::run(Settings::default())
|
iced::program(Pokedex::title, Pokedex::update, Pokedex::view)
|
||||||
|
.load(Pokedex::search)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
enum Pokedex {
|
enum Pokedex {
|
||||||
|
#[default]
|
||||||
Loading,
|
Loading,
|
||||||
Loaded { pokemon: Pokemon },
|
Loaded {
|
||||||
|
pokemon: Pokemon,
|
||||||
|
},
|
||||||
Errored,
|
Errored,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,17 +24,9 @@ enum Message {
|
||||||
Search,
|
Search,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Pokedex {
|
impl Pokedex {
|
||||||
type Message = Message;
|
fn search() -> Command<Message> {
|
||||||
type Theme = Theme;
|
Command::perform(Pokemon::search(), Message::PokemonFound)
|
||||||
type Executor = iced::executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Pokedex, Command<Message>) {
|
|
||||||
(
|
|
||||||
Pokedex::Loading,
|
|
||||||
Command::perform(Pokemon::search(), Message::PokemonFound),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
|
|
@ -59,7 +56,7 @@ impl Application for Pokedex {
|
||||||
_ => {
|
_ => {
|
||||||
*self = Pokedex::Loading;
|
*self = Pokedex::Loading;
|
||||||
|
|
||||||
Command::perform(Pokemon::search(), Message::PokemonFound)
|
Self::search()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use iced::widget::{column, progress_bar, slider};
|
use iced::widget::{column, progress_bar, slider};
|
||||||
use iced::{Element, Sandbox, Settings};
|
use iced::Element;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Progress::run(Settings::default())
|
iced::run("Progress Bar - Iced", Progress::update, Progress::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -15,17 +15,7 @@ enum Message {
|
||||||
SliderChanged(f32),
|
SliderChanged(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Progress {
|
impl Progress {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("A simple Progressbar")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::SliderChanged(x) => self.value = x,
|
Message::SliderChanged(x) => self.value = x,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
column, container, pick_list, qr_code, row, text, text_input,
|
column, container, pick_list, qr_code, row, text, text_input,
|
||||||
};
|
};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings, Theme};
|
use iced::{Alignment, Element, Length, Theme};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
QRGenerator::run(Settings::default())
|
iced::program(
|
||||||
|
"QR Code Generator - Iced",
|
||||||
|
QRGenerator::update,
|
||||||
|
QRGenerator::view,
|
||||||
|
)
|
||||||
|
.theme(QRGenerator::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -20,17 +26,7 @@ enum Message {
|
||||||
ThemeChanged(Theme),
|
ThemeChanged(Theme),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for QRGenerator {
|
impl QRGenerator {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
QRGenerator::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("QR Code Generator - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::DataChanged(mut data) => {
|
Message::DataChanged(mut data) => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
use iced::alignment;
|
use iced::alignment;
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::widget::{button, column, container, image, row, text, text_input};
|
use iced::widget::{button, column, container, image, row, text, text_input};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::window::screenshot::{self, Screenshot};
|
use iced::window::screenshot::{self, Screenshot};
|
||||||
use iced::{
|
use iced::{
|
||||||
Alignment, Application, Command, ContentFit, Element, Length, Rectangle,
|
Alignment, Command, ContentFit, Element, Length, Rectangle, Subscription,
|
||||||
Subscription, Theme,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use ::image as img;
|
use ::image as img;
|
||||||
|
|
@ -15,9 +13,12 @@ use ::image::ColorType;
|
||||||
fn main() -> iced::Result {
|
fn main() -> iced::Result {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Example::run(iced::Settings::default())
|
iced::program("Screenshot - Iced", Example::update, Example::view)
|
||||||
|
.subscription(Example::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct Example {
|
struct Example {
|
||||||
screenshot: Option<Screenshot>,
|
screenshot: Option<Screenshot>,
|
||||||
saved_png_path: Option<Result<String, PngError>>,
|
saved_png_path: Option<Result<String, PngError>>,
|
||||||
|
|
@ -42,33 +43,8 @@ enum Message {
|
||||||
HeightInputChanged(Option<u32>),
|
HeightInputChanged(Option<u32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
|
||||||
(
|
|
||||||
Example {
|
|
||||||
screenshot: None,
|
|
||||||
saved_png_path: None,
|
|
||||||
png_saving: false,
|
|
||||||
crop_error: None,
|
|
||||||
x_input_value: None,
|
|
||||||
y_input_value: None,
|
|
||||||
width_input_value: None,
|
|
||||||
height_input_value: None,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
"Screenshot".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Screenshot => {
|
Message::Screenshot => {
|
||||||
return iced::window::screenshot(
|
return iced::window::screenshot(
|
||||||
|
|
@ -130,7 +106,7 @@ impl Application for Example {
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, Self::Message> {
|
fn view(&self) -> Element<'_, Message> {
|
||||||
let image: Element<Message> = if let Some(screenshot) = &self.screenshot
|
let image: Element<Message> = if let Some(screenshot) = &self.screenshot
|
||||||
{
|
{
|
||||||
image(image::Handle::from_pixels(
|
image(image::Handle::from_pixels(
|
||||||
|
|
@ -259,7 +235,7 @@ impl Application for Example {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
use keyboard::key;
|
use keyboard::key;
|
||||||
|
|
||||||
keyboard::on_key_press(|key, _modifiers| {
|
keyboard::on_key_press(|key, _modifiers| {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,22 @@
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::scrollable::Properties;
|
use iced::widget::scrollable::Properties;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, horizontal_space, progress_bar, radio, row,
|
button, column, container, horizontal_space, progress_bar, radio, row,
|
||||||
scrollable, slider, text, vertical_space, Scrollable,
|
scrollable, slider, text, vertical_space, Scrollable,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Alignment, Border, Color, Command, Element, Length, Theme};
|
||||||
Alignment, Application, Border, Color, Command, Element, Length, Settings,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
static SCROLLABLE_ID: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique);
|
static SCROLLABLE_ID: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique);
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
ScrollableDemo::run(Settings::default())
|
iced::program(
|
||||||
|
"Scrollable - Iced",
|
||||||
|
ScrollableDemo::update,
|
||||||
|
ScrollableDemo::view,
|
||||||
|
)
|
||||||
|
.theme(ScrollableDemo::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScrollableDemo {
|
struct ScrollableDemo {
|
||||||
|
|
@ -45,28 +47,16 @@ enum Message {
|
||||||
Scrolled(scrollable::Viewport),
|
Scrolled(scrollable::Viewport),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for ScrollableDemo {
|
impl ScrollableDemo {
|
||||||
type Executor = executor::Default;
|
fn new() -> Self {
|
||||||
type Message = Message;
|
ScrollableDemo {
|
||||||
type Theme = Theme;
|
scrollable_direction: Direction::Vertical,
|
||||||
type Flags = ();
|
scrollbar_width: 10,
|
||||||
|
scrollbar_margin: 0,
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
scroller_width: 10,
|
||||||
(
|
current_scroll_offset: scrollable::RelativeOffset::START,
|
||||||
ScrollableDemo {
|
alignment: scrollable::Alignment::Start,
|
||||||
scrollable_direction: Direction::Vertical,
|
}
|
||||||
scrollbar_width: 10,
|
|
||||||
scrollbar_margin: 0,
|
|
||||||
scroller_width: 10,
|
|
||||||
current_scroll_offset: scrollable::RelativeOffset::START,
|
|
||||||
alignment: scrollable::Alignment::Start,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Scrollable - Iced")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
|
|
@ -340,11 +330,17 @@ impl Application for ScrollableDemo {
|
||||||
container(content).padding(20).center_x().center_y().into()
|
container(content).padding(20).center_x().center_y().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Self::Theme {
|
fn theme(&self) -> Theme {
|
||||||
Theme::Dark
|
Theme::Dark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ScrollableDemo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Appearance {
|
fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Appearance {
|
||||||
progress_bar::Appearance {
|
progress_bar::Appearance {
|
||||||
background: theme.extended_palette().background.strong.color.into(),
|
background: theme.extended_palette().background.strong.color.into(),
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,23 @@
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use iced::executor;
|
|
||||||
use iced::mouse;
|
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};
|
||||||
use iced::{
|
use iced::{Color, Length, Point, Rectangle, Renderer, Size, Theme};
|
||||||
Application, Color, Command, Length, Point, Rectangle, Renderer, Settings,
|
|
||||||
Size, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
fn main() -> iced::Result {
|
fn main() -> iced::Result {
|
||||||
SierpinskiEmulator::run(Settings {
|
iced::program(
|
||||||
antialiasing: true,
|
"Sierpinski Triangle - Iced",
|
||||||
..Settings::default()
|
SierpinskiEmulator::update,
|
||||||
})
|
SierpinskiEmulator::view,
|
||||||
|
)
|
||||||
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
struct SierpinskiEmulator {
|
struct SierpinskiEmulator {
|
||||||
graph: SierpinskiGraph,
|
graph: SierpinskiGraph,
|
||||||
}
|
}
|
||||||
|
|
@ -31,27 +29,8 @@ pub enum Message {
|
||||||
PointRemoved,
|
PointRemoved,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for SierpinskiEmulator {
|
impl SierpinskiEmulator {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, message: Message) {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, iced::Command<Self::Message>) {
|
|
||||||
let emulator = SierpinskiEmulator {
|
|
||||||
graph: SierpinskiGraph::new(),
|
|
||||||
};
|
|
||||||
(emulator, Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
"Sierpinski Triangle Emulator".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(
|
|
||||||
&mut self,
|
|
||||||
message: Self::Message,
|
|
||||||
) -> iced::Command<Self::Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::IterationSet(cur_iter) => {
|
Message::IterationSet(cur_iter) => {
|
||||||
self.graph.iteration = cur_iter;
|
self.graph.iteration = cur_iter;
|
||||||
|
|
@ -67,11 +46,9 @@ impl Application for SierpinskiEmulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.graph.redraw();
|
self.graph.redraw();
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> iced::Element<'_, Self::Message> {
|
fn view(&self) -> iced::Element<'_, Message> {
|
||||||
column![
|
column![
|
||||||
Canvas::new(&self.graph)
|
Canvas::new(&self.graph)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
|
|
@ -167,10 +144,6 @@ impl canvas::Program<Message> for SierpinskiGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SierpinskiGraph {
|
impl SierpinskiGraph {
|
||||||
fn new() -> SierpinskiGraph {
|
|
||||||
SierpinskiGraph::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn redraw(&mut self) {
|
fn redraw(&mut self) {
|
||||||
self.cache.clear();
|
self.cache.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use iced::widget::{column, container, slider, text, vertical_slider};
|
use iced::widget::{column, container, slider, text, vertical_slider};
|
||||||
use iced::{Element, Length, Sandbox, Settings};
|
use iced::{Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Slider::run(Settings::default())
|
iced::run("Slider - Iced", Slider::update, Slider::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -17,10 +17,8 @@ pub struct Slider {
|
||||||
shift_step: u8,
|
shift_step: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Slider {
|
impl Slider {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
|
|
||||||
fn new() -> Slider {
|
|
||||||
Slider {
|
Slider {
|
||||||
value: 50,
|
value: 50,
|
||||||
default: 50,
|
default: 50,
|
||||||
|
|
@ -29,10 +27,6 @@ impl Sandbox for Slider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Slider - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::SliderChanged(value) => {
|
Message::SliderChanged(value) => {
|
||||||
|
|
@ -75,3 +69,9 @@ impl Sandbox for Slider {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Slider {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
//! Inspired by the example found in the MDN docs[1].
|
//! Inspired by the example found in the MDN docs[1].
|
||||||
//!
|
//!
|
||||||
//! [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::executor;
|
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::widget::canvas;
|
use iced::widget::canvas;
|
||||||
use iced::widget::canvas::gradient;
|
use iced::widget::canvas::gradient;
|
||||||
|
|
@ -15,8 +13,8 @@ use iced::widget::canvas::stroke::{self, Stroke};
|
||||||
use iced::widget::canvas::Path;
|
use iced::widget::canvas::Path;
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{
|
||||||
Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
|
Color, Element, Length, Point, Rectangle, Renderer, Size, Subscription,
|
||||||
Settings, Size, Subscription, Theme, Vector,
|
Theme, Vector,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
@ -24,12 +22,17 @@ use std::time::Instant;
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
SolarSystem::run(Settings {
|
iced::program(
|
||||||
antialiasing: true,
|
"Solar System - Iced",
|
||||||
..Settings::default()
|
SolarSystem::update,
|
||||||
})
|
SolarSystem::view,
|
||||||
|
)
|
||||||
|
.subscription(SolarSystem::subscription)
|
||||||
|
.theme(SolarSystem::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct SolarSystem {
|
struct SolarSystem {
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
@ -39,33 +42,13 @@ enum Message {
|
||||||
Tick(Instant),
|
Tick(Instant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for SolarSystem {
|
impl SolarSystem {
|
||||||
type Executor = executor::Default;
|
fn update(&mut self, message: Message) {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
SolarSystem {
|
|
||||||
state: State::new(),
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Solar system - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Tick(instant) => {
|
Message::Tick(instant) => {
|
||||||
self.state.update(instant);
|
self.state.update(instant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
|
@ -76,14 +59,7 @@ impl Application for SolarSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
fn theme(&self) -> Theme {
|
||||||
Theme::Dark
|
Theme::Moonfly
|
||||||
}
|
|
||||||
|
|
||||||
fn style(&self, _theme: &Theme) -> application::Appearance {
|
|
||||||
application::Appearance {
|
|
||||||
background_color: Color::BLACK,
|
|
||||||
text_color: Color::WHITE,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
@ -224,3 +200,9 @@ impl<Message> canvas::Program<Message> for State {
|
||||||
vec![background, system]
|
vec![background, system]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for State {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,31 @@
|
||||||
use iced::alignment;
|
use iced::alignment;
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::time;
|
use iced::time;
|
||||||
use iced::widget::{button, column, container, row, text};
|
use iced::widget::{button, column, container, row, text};
|
||||||
use iced::{
|
use iced::{Alignment, Element, Length, Subscription, Theme};
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Stopwatch::run(Settings::default())
|
iced::program("Stopwatch - Iced", Stopwatch::update, Stopwatch::view)
|
||||||
|
.subscription(Stopwatch::subscription)
|
||||||
|
.theme(Stopwatch::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct Stopwatch {
|
struct Stopwatch {
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
enum State {
|
enum State {
|
||||||
|
#[default]
|
||||||
Idle,
|
Idle,
|
||||||
Ticking { last_tick: Instant },
|
Ticking {
|
||||||
|
last_tick: Instant,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -31,27 +35,8 @@ enum Message {
|
||||||
Tick(Instant),
|
Tick(Instant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Stopwatch {
|
impl Stopwatch {
|
||||||
type Message = Message;
|
fn update(&mut self, message: Message) {
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Stopwatch, Command<Message>) {
|
|
||||||
(
|
|
||||||
Stopwatch {
|
|
||||||
duration: Duration::default(),
|
|
||||||
state: State::Idle,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Stopwatch - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Toggle => match self.state {
|
Message::Toggle => match self.state {
|
||||||
State::Idle => {
|
State::Idle => {
|
||||||
|
|
@ -73,8 +58,6 @@ impl Application for Stopwatch {
|
||||||
self.duration = Duration::default();
|
self.duration = Duration::default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ use iced::widget::{
|
||||||
progress_bar, row, scrollable, slider, text, text_input, toggler,
|
progress_bar, row, scrollable, slider, text, text_input, toggler,
|
||||||
vertical_rule, vertical_space,
|
vertical_rule, vertical_space,
|
||||||
};
|
};
|
||||||
use iced::{Alignment, Element, Length, Sandbox, Settings, Theme};
|
use iced::{Alignment, Element, Length, Theme};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Styling::run(Settings::default())
|
iced::program("Styling - Iced", Styling::update, Styling::view)
|
||||||
|
.theme(Styling::theme)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -28,17 +30,7 @@ enum Message {
|
||||||
TogglerToggled(bool),
|
TogglerToggled(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Styling {
|
impl Styling {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Styling::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Styling - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::ThemeChanged(theme) => {
|
Message::ThemeChanged(theme) => {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use iced::widget::{checkbox, column, container, svg};
|
use iced::widget::{checkbox, column, container, svg};
|
||||||
use iced::{color, Element, Length, Sandbox, Settings};
|
use iced::{color, Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Tiger::run(Settings::default())
|
iced::run("SVG - Iced", Tiger::update, Tiger::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -15,18 +15,8 @@ pub enum Message {
|
||||||
ToggleColorFilter(bool),
|
ToggleColorFilter(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Tiger {
|
impl Tiger {
|
||||||
type Message = Message;
|
fn update(&mut self, message: Message) {
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Tiger::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("SVG - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) {
|
|
||||||
match message {
|
match message {
|
||||||
Message::ToggleColorFilter(apply_color_filter) => {
|
Message::ToggleColorFilter(apply_color_filter) => {
|
||||||
self.apply_color_filter = apply_color_filter;
|
self.apply_color_filter = apply_color_filter;
|
||||||
|
|
@ -34,7 +24,7 @@ impl Sandbox for Tiger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Self::Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
let handle = svg::Handle::from_path(format!(
|
let handle = svg::Handle::from_path(format!(
|
||||||
"{}/resources/tiger.svg",
|
"{}/resources/tiger.svg",
|
||||||
env!("CARGO_MANIFEST_DIR")
|
env!("CARGO_MANIFEST_DIR")
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
use iced::widget::{button, column, container, text};
|
use iced::widget::{button, column, container, text};
|
||||||
use iced::{
|
use iced::{system, Command, Element, Length};
|
||||||
executor, system, Application, Command, Element, Length, Settings, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use bytesize::ByteSize;
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::program("System Information - Iced", Example::update, Example::view)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum Example {
|
enum Example {
|
||||||
|
#[default]
|
||||||
Loading,
|
Loading,
|
||||||
Loaded { information: system::Information },
|
Loaded {
|
||||||
|
information: system::Information,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -22,23 +23,7 @@ enum Message {
|
||||||
Refresh,
|
Refresh,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self::Loading,
|
|
||||||
system::fetch_information(Message::InformationReceived),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("System Information - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Refresh => {
|
Message::Refresh => {
|
||||||
|
|
@ -55,6 +40,8 @@ impl Application for Example {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
|
use bytesize::ByteSize;
|
||||||
|
|
||||||
let content: Element<_> = match self {
|
let content: Element<_> = match self {
|
||||||
Example::Loading => text("Loading...").size(40).into(),
|
Example::Loading => text("Loading...").size(40).into(),
|
||||||
Example::Loaded { information } => {
|
Example::Loaded { information } => {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,19 @@
|
||||||
use iced::event::{self, Event};
|
use iced::event::{self, Event};
|
||||||
use iced::executor;
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::keyboard::key;
|
use iced::keyboard::key;
|
||||||
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, Command, Element, Length, Subscription};
|
||||||
Alignment, Application, Command, Element, Length, Settings, Subscription,
|
|
||||||
};
|
|
||||||
|
|
||||||
use toast::{Status, Toast};
|
use toast::{Status, Toast};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
App::run(Settings::default())
|
iced::program("Toast - Iced", App::update, App::view)
|
||||||
|
.subscription(App::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct App {
|
struct App {
|
||||||
toasts: Vec<Toast>,
|
toasts: Vec<Toast>,
|
||||||
editing: Toast,
|
editing: Toast,
|
||||||
|
|
@ -34,32 +32,20 @@ enum Message {
|
||||||
Event(Event),
|
Event(Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for App {
|
impl App {
|
||||||
type Executor = executor::Default;
|
fn new() -> Self {
|
||||||
type Message = Message;
|
App {
|
||||||
type Theme = iced::Theme;
|
toasts: vec![Toast {
|
||||||
type Flags = ();
|
title: "Example Toast".into(),
|
||||||
|
body: "Add more toasts in the form below!".into(),
|
||||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
status: Status::Primary,
|
||||||
(
|
}],
|
||||||
App {
|
timeout_secs: toast::DEFAULT_TIMEOUT,
|
||||||
toasts: vec![Toast {
|
editing: Toast::default(),
|
||||||
title: "Example Toast".into(),
|
}
|
||||||
body: "Add more toasts in the form below!".into(),
|
|
||||||
status: Status::Primary,
|
|
||||||
}],
|
|
||||||
timeout_secs: toast::DEFAULT_TIMEOUT,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
String::from("Toast - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
|
||||||
event::listen().map(Message::Event)
|
event::listen().map(Message::Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,8 +92,8 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view<'a>(&'a self) -> Element<'a, Message> {
|
fn view(&self) -> Element<'_, Message> {
|
||||||
let subtitle = |title, content: Element<'a, Message>| {
|
let subtitle = |title, content: Element<'static, Message>| {
|
||||||
column![text(title).size(14), content].spacing(5)
|
column![text(title).size(14), content].spacing(5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -172,6 +158,12 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for App {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod toast {
|
mod toast {
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
use iced::alignment::{self, Alignment};
|
use iced::alignment::{self, Alignment};
|
||||||
use iced::font::{self, Font};
|
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
self, button, checkbox, column, container, keyed_column, row, scrollable,
|
self, button, checkbox, column, container, keyed_column, row, scrollable,
|
||||||
text, text_input, Text,
|
text, text_input, Text,
|
||||||
};
|
};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{Command, Element, Font, Length, Subscription};
|
||||||
Application, Command, Element, Length, Settings, Size, Subscription, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -20,17 +17,17 @@ pub fn main() -> iced::Result {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Todos::run(Settings {
|
iced::program(Todos::title, Todos::update, Todos::view)
|
||||||
window: window::Settings {
|
.load(Todos::load)
|
||||||
size: Size::new(500.0, 800.0),
|
.subscription(Todos::subscription)
|
||||||
..window::Settings::default()
|
.font(include_bytes!("../fonts/icons.ttf").as_slice())
|
||||||
},
|
.window_size((500.0, 800.0))
|
||||||
..Settings::default()
|
.run()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Default, Debug)]
|
||||||
enum Todos {
|
enum Todos {
|
||||||
|
#[default]
|
||||||
Loading,
|
Loading,
|
||||||
Loaded(State),
|
Loaded(State),
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +44,6 @@ struct State {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
Loaded(Result<SavedState, LoadError>),
|
Loaded(Result<SavedState, LoadError>),
|
||||||
FontLoaded(Result<(), font::Error>),
|
|
||||||
Saved(Result<(), SaveError>),
|
Saved(Result<(), SaveError>),
|
||||||
InputChanged(String),
|
InputChanged(String),
|
||||||
CreateTask,
|
CreateTask,
|
||||||
|
|
@ -57,21 +53,9 @@ enum Message {
|
||||||
ToggleFullscreen(window::Mode),
|
ToggleFullscreen(window::Mode),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Todos {
|
impl Todos {
|
||||||
type Message = Message;
|
fn load() -> Command<Message> {
|
||||||
type Theme = Theme;
|
Command::perform(SavedState::load(), Message::Loaded)
|
||||||
type Executor = iced::executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Todos, Command<Message>) {
|
|
||||||
(
|
|
||||||
Todos::Loading,
|
|
||||||
Command::batch(vec![
|
|
||||||
font::load(include_bytes!("../fonts/icons.ttf").as_slice())
|
|
||||||
.map(Message::FontLoaded),
|
|
||||||
Command::perform(SavedState::load(), Message::Loaded),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
|
|
@ -168,7 +152,7 @@ impl Application for Todos {
|
||||||
Message::ToggleFullscreen(mode) => {
|
Message::ToggleFullscreen(mode) => {
|
||||||
window::change_mode(window::Id::MAIN, mode)
|
window::change_mode(window::Id::MAIN, mode)
|
||||||
}
|
}
|
||||||
_ => Command::none(),
|
Message::Loaded(_) => Command::none(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !saved {
|
if !saved {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
use iced::widget::tooltip::Position;
|
use iced::widget::tooltip::Position;
|
||||||
use iced::widget::{button, container, tooltip};
|
use iced::widget::{button, container, tooltip};
|
||||||
use iced::{Element, Length, Sandbox, Settings};
|
use iced::{Element, Length};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::run("Tooltip - Iced", Tooltip::update, Tooltip::view)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Example {
|
#[derive(Default)]
|
||||||
|
struct Tooltip {
|
||||||
position: Position,
|
position: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -15,28 +16,16 @@ enum Message {
|
||||||
ChangePosition,
|
ChangePosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Tooltip {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
position: Position::Bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Tooltip - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::ChangePosition => {
|
Message::ChangePosition => {
|
||||||
let position = match &self.position {
|
let position = match &self.position {
|
||||||
Position::FollowCursor => Position::Top,
|
|
||||||
Position::Top => Position::Bottom,
|
Position::Top => Position::Bottom,
|
||||||
Position::Bottom => Position::Left,
|
Position::Bottom => Position::Left,
|
||||||
Position::Left => Position::Right,
|
Position::Left => Position::Right,
|
||||||
Position::Right => Position::FollowCursor,
|
Position::Right => Position::FollowCursor,
|
||||||
|
Position::FollowCursor => Position::Top,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.position = position;
|
self.position = position;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use iced::widget::{
|
||||||
scrollable, slider, text, text_input, toggler, vertical_space,
|
scrollable, slider, text, text_input, toggler, vertical_space,
|
||||||
};
|
};
|
||||||
use iced::widget::{Button, Column, Container, Slider};
|
use iced::widget::{Button, Column, Container, Slider};
|
||||||
use iced::{Color, Element, Font, Length, Pixels, Sandbox, Settings};
|
use iced::{Color, Element, Font, Length, Pixels};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
|
@ -16,24 +16,18 @@ pub fn main() -> iced::Result {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
Tour::run(Settings::default())
|
iced::program(Tour::title, Tour::update, Tour::view)
|
||||||
|
.centered()
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Tour {
|
pub struct Tour {
|
||||||
steps: Steps,
|
steps: Steps,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Tour {
|
impl Tour {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Tour {
|
|
||||||
Tour {
|
|
||||||
steps: Steps::new(),
|
|
||||||
debug: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
format!("{} - Iced", self.steps.title())
|
format!("{} - Iced", self.steps.title())
|
||||||
}
|
}
|
||||||
|
|
@ -171,6 +165,12 @@ impl Steps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Steps {
|
||||||
|
fn default() -> Self {
|
||||||
|
Steps::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum Step {
|
enum Step {
|
||||||
Welcome,
|
Welcome,
|
||||||
Slider {
|
Slider {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
use iced::event::{self, Event};
|
use iced::event::{self, Event};
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{container, text};
|
use iced::widget::{container, text};
|
||||||
use iced::{
|
use iced::{Element, Length, Subscription};
|
||||||
Application, Command, Element, Length, Settings, Subscription, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
App::run(Settings::default())
|
iced::program("URL Handler - Iced", App::update, App::view)
|
||||||
|
.subscription(App::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -19,21 +18,8 @@ enum Message {
|
||||||
EventOccurred(Event),
|
EventOccurred(Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for App {
|
impl App {
|
||||||
type Message = Message;
|
fn update(&mut self, message: Message) {
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (App, Command<Message>) {
|
|
||||||
(App::default(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Url - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::EventOccurred(event) => {
|
Message::EventOccurred(event) => {
|
||||||
if let Event::PlatformSpecific(
|
if let Event::PlatformSpecific(
|
||||||
|
|
@ -45,9 +31,7 @@ impl Application for App {
|
||||||
self.url = Some(url);
|
self.url = Some(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,20 @@ use iced::mouse;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
canvas, checkbox, column, horizontal_space, row, slider, text,
|
canvas, checkbox, column, horizontal_space, row, slider, text,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{Element, Length, Point, Rectangle, Renderer, Theme, Vector};
|
||||||
Element, Length, Point, Rectangle, Renderer, Sandbox, Settings, Theme,
|
|
||||||
Vector,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
VectorialText::run(Settings {
|
iced::program(
|
||||||
antialiasing: true,
|
"Vectorial Text - Iced",
|
||||||
..Settings::default()
|
VectorialText::update,
|
||||||
})
|
VectorialText::view,
|
||||||
|
)
|
||||||
|
.theme(|_| Theme::Dark)
|
||||||
|
.antialiasing(true)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct VectorialText {
|
struct VectorialText {
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
@ -27,19 +29,7 @@ enum Message {
|
||||||
ToggleJapanese(bool),
|
ToggleJapanese(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for VectorialText {
|
impl VectorialText {
|
||||||
type Message = Message;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
state: State::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Vectorial Text - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) {
|
||||||
match message {
|
match message {
|
||||||
Message::SizeChanged(size) => {
|
Message::SizeChanged(size) => {
|
||||||
|
|
@ -106,10 +96,6 @@ impl Sandbox for VectorialText {
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::Dark
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
|
@ -170,3 +156,9 @@ impl<Message> canvas::Program<Message> for State {
|
||||||
vec![geometry]
|
vec![geometry]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for State {
|
||||||
|
fn default() -> Self {
|
||||||
|
State::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
use iced::event::{self, Event};
|
use iced::event::{self, Event};
|
||||||
use iced::executor;
|
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
column, container, horizontal_space, row, scrollable, text, vertical_space,
|
column, container, horizontal_space, row, scrollable, text, vertical_space,
|
||||||
};
|
};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{
|
||||||
Alignment, Application, Color, Command, Element, Font, Length, Point,
|
Alignment, Color, Command, Element, Font, Length, Point, Rectangle,
|
||||||
Rectangle, Settings, Subscription, Theme,
|
Subscription, Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
iced::program("Visible Bounds - Iced", Example::update, Example::view)
|
||||||
|
.subscription(Example::subscription)
|
||||||
|
.theme(|_| Theme::Dark)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct Example {
|
struct Example {
|
||||||
mouse_position: Option<Point>,
|
mouse_position: Option<Point>,
|
||||||
outer_bounds: Option<Rectangle>,
|
outer_bounds: Option<Rectangle>,
|
||||||
|
|
@ -29,27 +32,7 @@ enum Message {
|
||||||
InnerBoundsFetched(Option<Rectangle>),
|
InnerBoundsFetched(Option<Rectangle>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Example {
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Flags = ();
|
|
||||||
type Executor = executor::Default;
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
mouse_position: None,
|
|
||||||
outer_bounds: None,
|
|
||||||
inner_bounds: None,
|
|
||||||
},
|
|
||||||
Command::none(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Visible bounds - Iced")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::MouseMoved(position) => {
|
Message::MouseMoved(position) => {
|
||||||
|
|
@ -172,10 +155,6 @@ impl Application for Example {
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::Dark
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
mod echo;
|
mod echo;
|
||||||
|
|
||||||
use iced::alignment::{self, Alignment};
|
use iced::alignment::{self, Alignment};
|
||||||
use iced::executor;
|
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, row, scrollable, text, text_input,
|
button, column, container, row, scrollable, text, text_input,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{color, Command, Element, Length, Subscription};
|
||||||
color, Application, Command, Element, Length, Settings, Subscription, Theme,
|
|
||||||
};
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
WebSocket::run(Settings::default())
|
iced::program("WebSocket - Iced", WebSocket::update, WebSocket::view)
|
||||||
|
.load(WebSocket::load)
|
||||||
|
.subscription(WebSocket::subscription)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -29,21 +29,9 @@ enum Message {
|
||||||
Server,
|
Server,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for WebSocket {
|
impl WebSocket {
|
||||||
type Message = Message;
|
fn load() -> Command<Message> {
|
||||||
type Theme = Theme;
|
Command::perform(echo::server::run(), |_| Message::Server)
|
||||||
type Flags = ();
|
|
||||||
type Executor = executor::Default;
|
|
||||||
|
|
||||||
fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
|
|
||||||
(
|
|
||||||
Self::default(),
|
|
||||||
Command::perform(echo::server::run(), |_| Message::Server),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("WebSocket - Iced")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ mod cache;
|
||||||
|
|
||||||
pub use cache::Cache;
|
pub use cache::Cache;
|
||||||
|
|
||||||
use crate::core::{Point, Rectangle, Size, Transformation, Vector};
|
use crate::core::{Point, Radians, Rectangle, Size, Transformation, Vector};
|
||||||
use crate::graphics::geometry::{Fill, Path, Stroke, Text};
|
use crate::graphics::geometry::{Fill, Path, Stroke, Text};
|
||||||
use crate::Renderer;
|
use crate::Renderer;
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ impl Frame {
|
||||||
|
|
||||||
/// Applies a rotation in radians to the current transform of the [`Frame`].
|
/// Applies a rotation in radians to the current transform of the [`Frame`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotate(&mut self, angle: f32) {
|
pub fn rotate(&mut self, angle: impl Into<Radians>) {
|
||||||
delegate!(self, frame, frame.rotate(angle));
|
delegate!(self, frame, frame.rotate(angle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,12 @@ impl<T> Command<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Message> From<()> for Command<Message> {
|
||||||
|
fn from(_value: ()) -> Self {
|
||||||
|
Self::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Command<T> {
|
impl<T> fmt::Debug for Command<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let Command(command) = self;
|
let Command(command) = self;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
//! Leverage advanced concepts like custom widgets.
|
//! Leverage advanced concepts like custom widgets.
|
||||||
|
pub use crate::application::Application;
|
||||||
pub use crate::core::clipboard::{self, Clipboard};
|
pub use crate::core::clipboard::{self, Clipboard};
|
||||||
pub use crate::core::image;
|
pub use crate::core::image;
|
||||||
pub use crate::core::layout::{self, Layout};
|
pub use crate::core::layout::{self, Layout};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
//! Build interactive cross-platform applications.
|
//! Build interactive cross-platform applications.
|
||||||
|
use crate::shell::application;
|
||||||
use crate::{Command, Element, Executor, Settings, Subscription};
|
use crate::{Command, Element, Executor, Settings, Subscription};
|
||||||
|
|
||||||
use crate::shell::application;
|
pub use application::{Appearance, DefaultStyle};
|
||||||
|
|
||||||
pub use application::{default, Appearance, DefaultStyle};
|
|
||||||
|
|
||||||
/// An interactive cross-platform application.
|
/// An interactive cross-platform application.
|
||||||
///
|
///
|
||||||
|
|
@ -15,9 +14,7 @@ pub use application::{default, Appearance, DefaultStyle};
|
||||||
/// document.
|
/// document.
|
||||||
///
|
///
|
||||||
/// An [`Application`] can execute asynchronous actions by returning a
|
/// An [`Application`] can execute asynchronous actions by returning a
|
||||||
/// [`Command`] in some of its methods. If you do not intend to perform any
|
/// [`Command`] in some of its methods.
|
||||||
/// background work in your program, the [`Sandbox`] trait offers a simplified
|
|
||||||
/// interface.
|
|
||||||
///
|
///
|
||||||
/// When using an [`Application`] with the `debug` feature enabled, a debug view
|
/// When using an [`Application`] with the `debug` feature enabled, a debug view
|
||||||
/// can be toggled by pressing `F12`.
|
/// can be toggled by pressing `F12`.
|
||||||
|
|
@ -61,8 +58,9 @@ pub use application::{default, Appearance, DefaultStyle};
|
||||||
/// says "Hello, world!":
|
/// says "Hello, world!":
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
/// use iced::advanced::Application;
|
||||||
/// use iced::executor;
|
/// use iced::executor;
|
||||||
/// use iced::{Application, Command, Element, Settings, Theme};
|
/// use iced::{Command, Element, Settings, Theme};
|
||||||
///
|
///
|
||||||
/// pub fn main() -> iced::Result {
|
/// pub fn main() -> iced::Result {
|
||||||
/// Hello::run(Settings::default())
|
/// Hello::run(Settings::default())
|
||||||
|
|
|
||||||
106
src/lib.rs
106
src/lib.rs
|
|
@ -63,8 +63,8 @@
|
||||||
//! ```
|
//! ```
|
||||||
//! #[derive(Debug, Clone, Copy)]
|
//! #[derive(Debug, Clone, Copy)]
|
||||||
//! pub enum Message {
|
//! pub enum Message {
|
||||||
//! IncrementPressed,
|
//! Increment,
|
||||||
//! DecrementPressed,
|
//! Decrement,
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
//! #
|
//! #
|
||||||
//! # #[derive(Debug, Clone, Copy)]
|
//! # #[derive(Debug, Clone, Copy)]
|
||||||
//! # pub enum Message {
|
//! # pub enum Message {
|
||||||
//! # IncrementPressed,
|
//! # Increment,
|
||||||
//! # DecrementPressed,
|
//! # Decrement,
|
||||||
//! # }
|
//! # }
|
||||||
//! #
|
//! #
|
||||||
//! use iced::widget::{button, column, text, Column};
|
//! use iced::widget::{button, column, text, Column};
|
||||||
|
|
@ -90,15 +90,15 @@
|
||||||
//! // We use a column: a simple vertical layout
|
//! // We use a column: a simple vertical layout
|
||||||
//! column![
|
//! column![
|
||||||
//! // The increment button. We tell it to produce an
|
//! // The increment button. We tell it to produce an
|
||||||
//! // `IncrementPressed` message when pressed
|
//! // `Increment` message when pressed
|
||||||
//! button("+").on_press(Message::IncrementPressed),
|
//! button("+").on_press(Message::Increment),
|
||||||
//!
|
//!
|
||||||
//! // We show the value of the counter here
|
//! // We show the value of the counter here
|
||||||
//! text(self.value).size(50),
|
//! text(self.value).size(50),
|
||||||
//!
|
//!
|
||||||
//! // The decrement button. We tell it to produce a
|
//! // The decrement button. We tell it to produce a
|
||||||
//! // `DecrementPressed` message when pressed
|
//! // `Decrement` message when pressed
|
||||||
//! button("-").on_press(Message::DecrementPressed),
|
//! button("-").on_press(Message::Decrement),
|
||||||
//! ]
|
//! ]
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
|
|
@ -115,18 +115,18 @@
|
||||||
//! #
|
//! #
|
||||||
//! # #[derive(Debug, Clone, Copy)]
|
//! # #[derive(Debug, Clone, Copy)]
|
||||||
//! # pub enum Message {
|
//! # pub enum Message {
|
||||||
//! # IncrementPressed,
|
//! # Increment,
|
||||||
//! # DecrementPressed,
|
//! # Decrement,
|
||||||
//! # }
|
//! # }
|
||||||
//! impl Counter {
|
//! impl Counter {
|
||||||
//! // ...
|
//! // ...
|
||||||
//!
|
//!
|
||||||
//! pub fn update(&mut self, message: Message) {
|
//! pub fn update(&mut self, message: Message) {
|
||||||
//! match message {
|
//! match message {
|
||||||
//! Message::IncrementPressed => {
|
//! Message::Increment => {
|
||||||
//! self.value += 1;
|
//! self.value += 1;
|
||||||
//! }
|
//! }
|
||||||
//! Message::DecrementPressed => {
|
//! Message::Decrement => {
|
||||||
//! self.value -= 1;
|
//! self.value -= 1;
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
|
|
@ -134,8 +134,22 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! And that's everything! We just wrote a whole user interface. Iced is now
|
//! And that's everything! We just wrote a whole user interface. Let's run it:
|
||||||
//! able to:
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! # #[derive(Default)]
|
||||||
|
//! # struct Counter;
|
||||||
|
//! # impl Counter {
|
||||||
|
//! # fn update(&mut self, _message: ()) {}
|
||||||
|
//! # fn view(&self) -> iced::Element<()> { unimplemented!() }
|
||||||
|
//! # }
|
||||||
|
//! #
|
||||||
|
//! fn main() -> iced::Result {
|
||||||
|
//! iced::run("A cool counter", Counter::update, Counter::view)
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Iced will automatically:
|
||||||
//!
|
//!
|
||||||
//! 1. Take the result of our __view logic__ and layout its widgets.
|
//! 1. Take the result of our __view logic__ and layout its widgets.
|
||||||
//! 1. Process events from our system and produce __messages__ for our
|
//! 1. Process events from our system and produce __messages__ for our
|
||||||
|
|
@ -143,11 +157,11 @@
|
||||||
//! 1. Draw the resulting user interface.
|
//! 1. Draw the resulting user interface.
|
||||||
//!
|
//!
|
||||||
//! # Usage
|
//! # Usage
|
||||||
//! The [`Application`] and [`Sandbox`] traits should get you started quickly,
|
//! Use [`run`] or the [`program`] builder.
|
||||||
//! streamlining all the process described above!
|
|
||||||
//!
|
//!
|
||||||
//! [Elm]: https://elm-lang.org/
|
//! [Elm]: https://elm-lang.org/
|
||||||
//! [The Elm Architecture]: https://guide.elm-lang.org/architecture/
|
//! [The Elm Architecture]: https://guide.elm-lang.org/architecture/
|
||||||
|
//! [`program`]: program()
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
|
|
@ -171,10 +185,10 @@ pub use iced_futures::futures;
|
||||||
#[cfg(feature = "highlighter")]
|
#[cfg(feature = "highlighter")]
|
||||||
pub use iced_highlighter as highlighter;
|
pub use iced_highlighter as highlighter;
|
||||||
|
|
||||||
|
mod application;
|
||||||
mod error;
|
mod error;
|
||||||
mod sandbox;
|
|
||||||
|
|
||||||
pub mod application;
|
pub mod program;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
@ -302,14 +316,13 @@ pub mod widget {
|
||||||
mod runtime {}
|
mod runtime {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use application::Application;
|
|
||||||
pub use command::Command;
|
pub use command::Command;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use event::Event;
|
pub use event::Event;
|
||||||
pub use executor::Executor;
|
pub use executor::Executor;
|
||||||
pub use font::Font;
|
pub use font::Font;
|
||||||
|
pub use program::Program;
|
||||||
pub use renderer::Renderer;
|
pub use renderer::Renderer;
|
||||||
pub use sandbox::Sandbox;
|
|
||||||
pub use settings::Settings;
|
pub use settings::Settings;
|
||||||
pub use subscription::Subscription;
|
pub use subscription::Subscription;
|
||||||
|
|
||||||
|
|
@ -323,7 +336,54 @@ pub type Element<
|
||||||
Renderer = crate::Renderer,
|
Renderer = crate::Renderer,
|
||||||
> = crate::core::Element<'a, Message, Theme, Renderer>;
|
> = crate::core::Element<'a, Message, Theme, Renderer>;
|
||||||
|
|
||||||
/// The result of running an [`Application`].
|
/// The result of running a [`Program`].
|
||||||
///
|
|
||||||
/// [`Application`]: crate::Application
|
|
||||||
pub type Result = std::result::Result<(), Error>;
|
pub type Result = std::result::Result<(), Error>;
|
||||||
|
|
||||||
|
/// Runs a basic iced application with default [`Settings`] given its title,
|
||||||
|
/// update, and view logic.
|
||||||
|
///
|
||||||
|
/// This is equivalent to chaining [`program`] with [`Program::run`].
|
||||||
|
///
|
||||||
|
/// [`program`]: program()
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```no_run
|
||||||
|
/// use iced::widget::{button, column, text, Column};
|
||||||
|
///
|
||||||
|
/// pub fn main() -> iced::Result {
|
||||||
|
/// iced::run("A counter", update, view)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[derive(Debug, Clone)]
|
||||||
|
/// enum Message {
|
||||||
|
/// Increment,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn update(value: &mut u64, message: Message) {
|
||||||
|
/// match message {
|
||||||
|
/// Message::Increment => *value += 1,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn view(value: &u64) -> Column<Message> {
|
||||||
|
/// column![
|
||||||
|
/// text(value),
|
||||||
|
/// button("+").on_press(Message::Increment),
|
||||||
|
/// ]
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn run<State, Message, Theme>(
|
||||||
|
title: impl program::Title<State> + 'static,
|
||||||
|
update: impl program::Update<State, Message> + 'static,
|
||||||
|
view: impl for<'a> program::View<'a, State, Message, Theme> + 'static,
|
||||||
|
) -> Result
|
||||||
|
where
|
||||||
|
State: Default + 'static,
|
||||||
|
Message: std::fmt::Debug + Send + 'static,
|
||||||
|
Theme: Default + program::DefaultStyle + 'static,
|
||||||
|
{
|
||||||
|
program(title, update, view).run()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use program::program;
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ pub use crate::application::{Appearance, DefaultStyle};
|
||||||
/// document and display only the contents of the `window::Id::MAIN` window.
|
/// document and display only the contents of the `window::Id::MAIN` window.
|
||||||
///
|
///
|
||||||
/// An [`Application`] can execute asynchronous actions by returning a
|
/// An [`Application`] can execute asynchronous actions by returning a
|
||||||
/// [`Command`] in some of its methods. If you do not intend to perform any
|
/// [`Command`] in some of its methods.
|
||||||
/// background work in your program, the [`Sandbox`] trait offers a simplified
|
|
||||||
/// interface.
|
|
||||||
///
|
///
|
||||||
/// When using an [`Application`] with the `debug` feature enabled, a debug view
|
/// When using an [`Application`] with the `debug` feature enabled, a debug view
|
||||||
/// can be toggled by pressing `F12`.
|
/// can be toggled by pressing `F12`.
|
||||||
|
|
|
||||||
851
src/program.rs
Normal file
851
src/program.rs
Normal file
|
|
@ -0,0 +1,851 @@
|
||||||
|
//! Create and run iced applications step by step.
|
||||||
|
//!
|
||||||
|
//! # Example
|
||||||
|
//! ```no_run
|
||||||
|
//! use iced::widget::{button, column, text, Column};
|
||||||
|
//! use iced::Theme;
|
||||||
|
//!
|
||||||
|
//! pub fn main() -> iced::Result {
|
||||||
|
//! iced::program("A counter", update, view)
|
||||||
|
//! .theme(|_| Theme::Dark)
|
||||||
|
//! .centered()
|
||||||
|
//! .run()
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! #[derive(Debug, Clone)]
|
||||||
|
//! enum Message {
|
||||||
|
//! Increment,
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn update(value: &mut u64, message: Message) {
|
||||||
|
//! match message {
|
||||||
|
//! Message::Increment => *value += 1,
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn view(value: &u64) -> Column<Message> {
|
||||||
|
//! column![
|
||||||
|
//! text(value),
|
||||||
|
//! button("+").on_press(Message::Increment),
|
||||||
|
//! ]
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
use crate::application::Application;
|
||||||
|
use crate::executor::{self, Executor};
|
||||||
|
use crate::window;
|
||||||
|
use crate::{Command, Element, Font, Result, Settings, Size, Subscription};
|
||||||
|
|
||||||
|
pub use crate::application::{Appearance, DefaultStyle};
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
/// Creates an iced [`Program`] given its title, update, and view logic.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```no_run
|
||||||
|
/// use iced::widget::{button, column, text, Column};
|
||||||
|
///
|
||||||
|
/// pub fn main() -> iced::Result {
|
||||||
|
/// iced::program("A counter", update, view).run()
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[derive(Debug, Clone)]
|
||||||
|
/// enum Message {
|
||||||
|
/// Increment,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn update(value: &mut u64, message: Message) {
|
||||||
|
/// match message {
|
||||||
|
/// Message::Increment => *value += 1,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn view(value: &u64) -> Column<Message> {
|
||||||
|
/// column![
|
||||||
|
/// text(value),
|
||||||
|
/// button("+").on_press(Message::Increment),
|
||||||
|
/// ]
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn program<State, Message, Theme>(
|
||||||
|
title: impl Title<State>,
|
||||||
|
update: impl Update<State, Message>,
|
||||||
|
view: impl for<'a> self::View<'a, State, Message, Theme>,
|
||||||
|
) -> Program<impl Definition<State = State, Message = Message, Theme = Theme>>
|
||||||
|
where
|
||||||
|
State: 'static,
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
Theme: Default + DefaultStyle,
|
||||||
|
{
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct Application<State, Message, Theme, Update, View> {
|
||||||
|
update: Update,
|
||||||
|
view: View,
|
||||||
|
_state: PhantomData<State>,
|
||||||
|
_message: PhantomData<Message>,
|
||||||
|
_theme: PhantomData<Theme>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State, Message, Theme, Update, View> Definition
|
||||||
|
for Application<State, Message, Theme, Update, View>
|
||||||
|
where
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
Theme: Default + DefaultStyle,
|
||||||
|
Update: self::Update<State, Message>,
|
||||||
|
View: for<'a> self::View<'a, State, Message, Theme>,
|
||||||
|
{
|
||||||
|
type State = State;
|
||||||
|
type Message = Message;
|
||||||
|
type Theme = Theme;
|
||||||
|
type Executor = executor::Default;
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.update.update(state, message).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.view.view(state).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Program {
|
||||||
|
raw: Application {
|
||||||
|
update,
|
||||||
|
view,
|
||||||
|
_state: PhantomData,
|
||||||
|
_message: PhantomData,
|
||||||
|
_theme: PhantomData,
|
||||||
|
},
|
||||||
|
settings: Settings::default(),
|
||||||
|
}
|
||||||
|
.title(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The underlying definition and configuration of an iced application.
|
||||||
|
///
|
||||||
|
/// You can use this API to create and run iced applications
|
||||||
|
/// step by step—without coupling your logic to a trait
|
||||||
|
/// or a specific type.
|
||||||
|
///
|
||||||
|
/// You can create a [`Program`] with the [`program`] helper.
|
||||||
|
///
|
||||||
|
/// [`run`]: Program::run
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Program<P: Definition> {
|
||||||
|
raw: P,
|
||||||
|
settings: Settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition> Program<P> {
|
||||||
|
/// Runs the underlying [`Application`] of the [`Program`].
|
||||||
|
///
|
||||||
|
/// The state of the [`Program`] must implement [`Default`].
|
||||||
|
/// If your state does not implement [`Default`], use [`run_with`]
|
||||||
|
/// instead.
|
||||||
|
///
|
||||||
|
/// [`run_with`]: Self::run_with
|
||||||
|
pub fn run(self) -> Result
|
||||||
|
where
|
||||||
|
Self: 'static,
|
||||||
|
P::State: Default,
|
||||||
|
{
|
||||||
|
self.run_with(P::State::default)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs the underlying [`Application`] of the [`Program`] with a
|
||||||
|
/// closure that creates the initial state.
|
||||||
|
pub fn run_with(
|
||||||
|
self,
|
||||||
|
initialize: impl Fn() -> P::State + Clone + 'static,
|
||||||
|
) -> Result
|
||||||
|
where
|
||||||
|
Self: 'static,
|
||||||
|
{
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct Instance<P: Definition, I> {
|
||||||
|
program: P,
|
||||||
|
state: P::State,
|
||||||
|
_initialize: PhantomData<I>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition, I: Fn() -> P::State> Application for Instance<P, I> {
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Flags = (P, I);
|
||||||
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
(program, initialize): Self::Flags,
|
||||||
|
) -> (Self, Command<Self::Message>) {
|
||||||
|
let state = initialize();
|
||||||
|
let command = program.load();
|
||||||
|
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
program,
|
||||||
|
state,
|
||||||
|
_initialize: PhantomData,
|
||||||
|
},
|
||||||
|
command,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
self.program.title(&self.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&mut self,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(&mut self.state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(
|
||||||
|
&self,
|
||||||
|
) -> crate::Element<'_, Self::Message, Self::Theme, crate::Renderer>
|
||||||
|
{
|
||||||
|
self.program.view(&self.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(&self) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(&self.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self) -> Self::Theme {
|
||||||
|
self.program.theme(&self.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, theme: &Self::Theme) -> Appearance {
|
||||||
|
self.program.style(&self.state, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self { raw, settings } = self;
|
||||||
|
|
||||||
|
Instance::run(Settings {
|
||||||
|
flags: (raw, initialize),
|
||||||
|
id: settings.id,
|
||||||
|
window: settings.window,
|
||||||
|
fonts: settings.fonts,
|
||||||
|
default_font: settings.default_font,
|
||||||
|
default_text_size: settings.default_text_size,
|
||||||
|
antialiasing: settings.antialiasing,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`Settings`] that will be used to run the [`Program`].
|
||||||
|
pub fn settings(self, settings: Settings) -> Self {
|
||||||
|
Self { settings, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`Settings::antialiasing`] of the [`Program`].
|
||||||
|
pub fn antialiasing(self, antialiasing: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
antialiasing,
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the default [`Font`] of the [`Program`].
|
||||||
|
pub fn default_font(self, default_font: Font) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
default_font,
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a font to the list of fonts that will be loaded at the start of the [`Program`].
|
||||||
|
pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
|
||||||
|
self.settings.fonts.push(font.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`window::Settings::position`] to [`window::Position::Centered`] in the [`Program`].
|
||||||
|
pub fn centered(self) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
window: window::Settings {
|
||||||
|
position: window::Position::Centered,
|
||||||
|
..self.settings.window
|
||||||
|
},
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`window::Settings::exit_on_close_request`] of the [`Program`].
|
||||||
|
pub fn exit_on_close_request(self, exit_on_close_request: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
window: window::Settings {
|
||||||
|
exit_on_close_request,
|
||||||
|
..self.settings.window
|
||||||
|
},
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`window::Settings::size`] of the [`Program`].
|
||||||
|
pub fn window_size(self, size: impl Into<Size>) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
window: window::Settings {
|
||||||
|
size: size.into(),
|
||||||
|
..self.settings.window
|
||||||
|
},
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`window::Settings::transparent`] of the [`Program`].
|
||||||
|
pub fn transparent(self, transparent: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
window: window::Settings {
|
||||||
|
transparent,
|
||||||
|
..self.settings.window
|
||||||
|
},
|
||||||
|
..self.settings
|
||||||
|
},
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`Title`] of the [`Program`].
|
||||||
|
pub(crate) fn title(
|
||||||
|
self,
|
||||||
|
title: impl Title<P::State>,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = P::State, Message = P::Message, Theme = P::Theme>,
|
||||||
|
> {
|
||||||
|
Program {
|
||||||
|
raw: with_title(self.raw, title),
|
||||||
|
settings: self.settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs the [`Command`] produced by the closure at startup.
|
||||||
|
pub fn load(
|
||||||
|
self,
|
||||||
|
f: impl Fn() -> Command<P::Message>,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = P::State, Message = P::Message, Theme = P::Theme>,
|
||||||
|
> {
|
||||||
|
Program {
|
||||||
|
raw: with_load(self.raw, f),
|
||||||
|
settings: self.settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the subscription logic of the [`Program`].
|
||||||
|
pub fn subscription(
|
||||||
|
self,
|
||||||
|
f: impl Fn(&P::State) -> Subscription<P::Message>,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = P::State, Message = P::Message, Theme = P::Theme>,
|
||||||
|
> {
|
||||||
|
Program {
|
||||||
|
raw: with_subscription(self.raw, f),
|
||||||
|
settings: self.settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the theme logic of the [`Program`].
|
||||||
|
pub fn theme(
|
||||||
|
self,
|
||||||
|
f: impl Fn(&P::State) -> P::Theme,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = P::State, Message = P::Message, Theme = P::Theme>,
|
||||||
|
> {
|
||||||
|
Program {
|
||||||
|
raw: with_theme(self.raw, f),
|
||||||
|
settings: self.settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the style logic of the [`Program`].
|
||||||
|
pub fn style(
|
||||||
|
self,
|
||||||
|
f: impl Fn(&P::State, &P::Theme) -> Appearance,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = P::State, Message = P::Message, Theme = P::Theme>,
|
||||||
|
> {
|
||||||
|
Program {
|
||||||
|
raw: with_style(self.raw, f),
|
||||||
|
settings: self.settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The internal definition of a [`Program`].
|
||||||
|
///
|
||||||
|
/// You should not need to implement this trait directly. Instead, use the
|
||||||
|
/// methods available in the [`Program`] struct.
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub trait Definition: Sized {
|
||||||
|
/// The state of the program.
|
||||||
|
type State;
|
||||||
|
|
||||||
|
/// The message of the program.
|
||||||
|
type Message: Send + std::fmt::Debug;
|
||||||
|
|
||||||
|
/// The theme of the program.
|
||||||
|
type Theme: Default + DefaultStyle;
|
||||||
|
|
||||||
|
/// The executor of the program.
|
||||||
|
type Executor: Executor;
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message>;
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message>;
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme>;
|
||||||
|
|
||||||
|
fn title(&self, _state: &Self::State) -> String {
|
||||||
|
String::from("A cool iced application!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
_state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
Subscription::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self, _state: &Self::State) -> Self::Theme {
|
||||||
|
Self::Theme::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, _state: &Self::State, theme: &Self::Theme) -> Appearance {
|
||||||
|
DefaultStyle::default_style(theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_title<P: Definition>(
|
||||||
|
program: P,
|
||||||
|
title: impl Title<P::State>,
|
||||||
|
) -> impl Definition<State = P::State, Message = P::Message, Theme = P::Theme> {
|
||||||
|
struct WithTitle<P, Title> {
|
||||||
|
program: P,
|
||||||
|
title: Title,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P, Title> Definition for WithTitle<P, Title>
|
||||||
|
where
|
||||||
|
P: Definition,
|
||||||
|
Title: self::Title<P::State>,
|
||||||
|
{
|
||||||
|
type State = P::State;
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
self.program.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.title.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.program.view(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
self.program.theme(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
theme: &Self::Theme,
|
||||||
|
) -> Appearance {
|
||||||
|
self.program.style(state, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithTitle { program, title }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_load<P: Definition>(
|
||||||
|
program: P,
|
||||||
|
f: impl Fn() -> Command<P::Message>,
|
||||||
|
) -> impl Definition<State = P::State, Message = P::Message, Theme = P::Theme> {
|
||||||
|
struct WithLoad<P, F> {
|
||||||
|
program: P,
|
||||||
|
load: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition, F> Definition for WithLoad<P, F>
|
||||||
|
where
|
||||||
|
F: Fn() -> Command<P::Message>,
|
||||||
|
{
|
||||||
|
type State = P::State;
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Executor = executor::Default;
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
Command::batch([self.program.load(), (self.load)()])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.program.view(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.program.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
self.program.theme(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
theme: &Self::Theme,
|
||||||
|
) -> Appearance {
|
||||||
|
self.program.style(state, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithLoad { program, load: f }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_subscription<P: Definition>(
|
||||||
|
program: P,
|
||||||
|
f: impl Fn(&P::State) -> Subscription<P::Message>,
|
||||||
|
) -> impl Definition<State = P::State, Message = P::Message, Theme = P::Theme> {
|
||||||
|
struct WithSubscription<P, F> {
|
||||||
|
program: P,
|
||||||
|
subscription: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition, F> Definition for WithSubscription<P, F>
|
||||||
|
where
|
||||||
|
F: Fn(&P::State) -> Subscription<P::Message>,
|
||||||
|
{
|
||||||
|
type State = P::State;
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Executor = executor::Default;
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
(self.subscription)(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
self.program.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.program.view(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.program.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
self.program.theme(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
theme: &Self::Theme,
|
||||||
|
) -> Appearance {
|
||||||
|
self.program.style(state, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithSubscription {
|
||||||
|
program,
|
||||||
|
subscription: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_theme<P: Definition>(
|
||||||
|
program: P,
|
||||||
|
f: impl Fn(&P::State) -> P::Theme,
|
||||||
|
) -> impl Definition<State = P::State, Message = P::Message, Theme = P::Theme> {
|
||||||
|
struct WithTheme<P, F> {
|
||||||
|
program: P,
|
||||||
|
theme: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition, F> Definition for WithTheme<P, F>
|
||||||
|
where
|
||||||
|
F: Fn(&P::State) -> P::Theme,
|
||||||
|
{
|
||||||
|
type State = P::State;
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
(self.theme)(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
self.program.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.program.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.program.view(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
theme: &Self::Theme,
|
||||||
|
) -> Appearance {
|
||||||
|
self.program.style(state, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithTheme { program, theme: f }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_style<P: Definition>(
|
||||||
|
program: P,
|
||||||
|
f: impl Fn(&P::State, &P::Theme) -> Appearance,
|
||||||
|
) -> impl Definition<State = P::State, Message = P::Message, Theme = P::Theme> {
|
||||||
|
struct WithStyle<P, F> {
|
||||||
|
program: P,
|
||||||
|
style: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition, F> Definition for WithStyle<P, F>
|
||||||
|
where
|
||||||
|
F: Fn(&P::State, &P::Theme) -> Appearance,
|
||||||
|
{
|
||||||
|
type State = P::State;
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn style(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
theme: &Self::Theme,
|
||||||
|
) -> Appearance {
|
||||||
|
(self.style)(state, theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self) -> Command<Self::Message> {
|
||||||
|
self.program.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.program.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
self.program.update(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.program.view(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
self.program.theme(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithStyle { program, style: f }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The title logic of some [`Program`].
|
||||||
|
///
|
||||||
|
/// This trait is implemented both for `&static str` and
|
||||||
|
/// any closure `Fn(&State) -> String`.
|
||||||
|
///
|
||||||
|
/// This trait allows the [`program`] builder to take any of them.
|
||||||
|
pub trait Title<State> {
|
||||||
|
/// Produces the title of the [`Program`].
|
||||||
|
fn title(&self, state: &State) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State> Title<State> for &'static str {
|
||||||
|
fn title(&self, _state: &State) -> String {
|
||||||
|
self.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, State> Title<State> for T
|
||||||
|
where
|
||||||
|
T: Fn(&State) -> String,
|
||||||
|
{
|
||||||
|
fn title(&self, state: &State) -> String {
|
||||||
|
self(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The update logic of some [`Program`].
|
||||||
|
///
|
||||||
|
/// This trait allows the [`program`] builder to take any closure that
|
||||||
|
/// returns any `Into<Command<Message>>`.
|
||||||
|
pub trait Update<State, Message> {
|
||||||
|
/// Processes the message and updates the state of the [`Program`].
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut State,
|
||||||
|
message: Message,
|
||||||
|
) -> impl Into<Command<Message>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, State, Message, C> Update<State, Message> for T
|
||||||
|
where
|
||||||
|
T: Fn(&mut State, Message) -> C,
|
||||||
|
C: Into<Command<Message>>,
|
||||||
|
{
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut State,
|
||||||
|
message: Message,
|
||||||
|
) -> impl Into<Command<Message>> {
|
||||||
|
self(state, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The view logic of some [`Program`].
|
||||||
|
///
|
||||||
|
/// This trait allows the [`program`] builder to take any closure that
|
||||||
|
/// returns any `Into<Element<'_, Message>>`.
|
||||||
|
pub trait View<'a, State, Message, Theme> {
|
||||||
|
/// Produces the widget of the [`Program`].
|
||||||
|
fn view(&self, state: &'a State) -> impl Into<Element<'a, Message, Theme>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T, State, Message, Theme, Widget> View<'a, State, Message, Theme> for T
|
||||||
|
where
|
||||||
|
T: Fn(&'a State) -> Widget,
|
||||||
|
State: 'static,
|
||||||
|
Widget: Into<Element<'a, Message, Theme>>,
|
||||||
|
{
|
||||||
|
fn view(&self, state: &'a State) -> impl Into<Element<'a, Message, Theme>> {
|
||||||
|
self(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
199
src/sandbox.rs
199
src/sandbox.rs
|
|
@ -1,199 +0,0 @@
|
||||||
use crate::application::{self, Application};
|
|
||||||
use crate::{Command, Element, Error, Settings, Subscription, Theme};
|
|
||||||
|
|
||||||
/// A sandboxed [`Application`].
|
|
||||||
///
|
|
||||||
/// If you are a just getting started with the library, this trait offers a
|
|
||||||
/// simpler interface than [`Application`].
|
|
||||||
///
|
|
||||||
/// Unlike an [`Application`], a [`Sandbox`] cannot run any asynchronous
|
|
||||||
/// actions or be initialized with some external flags. However, both traits
|
|
||||||
/// are very similar and upgrading from a [`Sandbox`] is very straightforward.
|
|
||||||
///
|
|
||||||
/// Therefore, it is recommended to always start by implementing this trait and
|
|
||||||
/// upgrade only once necessary.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// [The repository has a bunch of examples] that use the [`Sandbox`] trait:
|
|
||||||
///
|
|
||||||
/// - [`bezier_tool`], a Paint-like tool for drawing Bézier curves using the
|
|
||||||
/// [`Canvas widget`].
|
|
||||||
/// - [`counter`], the classic counter example explained in [the overview].
|
|
||||||
/// - [`custom_widget`], a demonstration of how to build a custom widget that
|
|
||||||
/// draws a circle.
|
|
||||||
/// - [`geometry`], a custom widget showcasing how to draw geometry with the
|
|
||||||
/// `Mesh2D` primitive in [`iced_wgpu`].
|
|
||||||
/// - [`pane_grid`], a grid of panes that can be split, resized, and
|
|
||||||
/// reorganized.
|
|
||||||
/// - [`progress_bar`], a simple progress bar that can be filled by using a
|
|
||||||
/// slider.
|
|
||||||
/// - [`styling`], an example showcasing custom styling with a light and dark
|
|
||||||
/// theme.
|
|
||||||
/// - [`svg`], an application that renders the [Ghostscript Tiger] by leveraging
|
|
||||||
/// the [`Svg` widget].
|
|
||||||
/// - [`tour`], a simple UI tour that can run both on native platforms and the
|
|
||||||
/// web!
|
|
||||||
///
|
|
||||||
/// [The repository has a bunch of examples]: https://github.com/iced-rs/iced/tree/0.12/examples
|
|
||||||
/// [`bezier_tool`]: https://github.com/iced-rs/iced/tree/0.12/examples/bezier_tool
|
|
||||||
/// [`counter`]: https://github.com/iced-rs/iced/tree/0.12/examples/counter
|
|
||||||
/// [`custom_widget`]: https://github.com/iced-rs/iced/tree/0.12/examples/custom_widget
|
|
||||||
/// [`geometry`]: https://github.com/iced-rs/iced/tree/0.12/examples/geometry
|
|
||||||
/// [`pane_grid`]: https://github.com/iced-rs/iced/tree/0.12/examples/pane_grid
|
|
||||||
/// [`progress_bar`]: https://github.com/iced-rs/iced/tree/0.12/examples/progress_bar
|
|
||||||
/// [`styling`]: https://github.com/iced-rs/iced/tree/0.12/examples/styling
|
|
||||||
/// [`svg`]: https://github.com/iced-rs/iced/tree/0.12/examples/svg
|
|
||||||
/// [`tour`]: https://github.com/iced-rs/iced/tree/0.12/examples/tour
|
|
||||||
/// [`Canvas widget`]: crate::widget::Canvas
|
|
||||||
/// [the overview]: index.html#overview
|
|
||||||
/// [`iced_wgpu`]: https://github.com/iced-rs/iced/tree/0.12/wgpu
|
|
||||||
/// [`Svg` widget]: crate::widget::Svg
|
|
||||||
/// [Ghostscript Tiger]: https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg
|
|
||||||
///
|
|
||||||
/// ## A simple "Hello, world!"
|
|
||||||
///
|
|
||||||
/// If you just want to get started, here is a simple [`Sandbox`] that
|
|
||||||
/// says "Hello, world!":
|
|
||||||
///
|
|
||||||
/// ```no_run
|
|
||||||
/// use iced::{Element, Sandbox, Settings};
|
|
||||||
///
|
|
||||||
/// pub fn main() -> iced::Result {
|
|
||||||
/// Hello::run(Settings::default())
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// struct Hello;
|
|
||||||
///
|
|
||||||
/// impl Sandbox for Hello {
|
|
||||||
/// type Message = ();
|
|
||||||
///
|
|
||||||
/// fn new() -> Hello {
|
|
||||||
/// Hello
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn title(&self) -> String {
|
|
||||||
/// String::from("A cool application")
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn update(&mut self, _message: Self::Message) {
|
|
||||||
/// // This application has no interactions
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn view(&self) -> Element<Self::Message> {
|
|
||||||
/// "Hello, world!".into()
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait Sandbox {
|
|
||||||
/// The type of __messages__ your [`Sandbox`] will produce.
|
|
||||||
type Message: std::fmt::Debug + Send;
|
|
||||||
|
|
||||||
/// Initializes the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// Here is where you should return the initial state of your app.
|
|
||||||
fn new() -> Self;
|
|
||||||
|
|
||||||
/// Returns the current title of the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// This title can be dynamic! The runtime will automatically update the
|
|
||||||
/// title of your application when necessary.
|
|
||||||
fn title(&self) -> String;
|
|
||||||
|
|
||||||
/// Handles a __message__ and updates the state of the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// This is where you define your __update logic__. All the __messages__,
|
|
||||||
/// produced by user interactions, will be handled by this method.
|
|
||||||
fn update(&mut self, message: Self::Message);
|
|
||||||
|
|
||||||
/// Returns the widgets to display in the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// These widgets can produce __messages__ based on user interaction.
|
|
||||||
fn view(&self) -> Element<'_, Self::Message>;
|
|
||||||
|
|
||||||
/// Returns the current [`Theme`] of the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// If you want to use your own custom theme type, you will have to use an
|
|
||||||
/// [`Application`].
|
|
||||||
///
|
|
||||||
/// By default, it returns [`Theme::default`].
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the current [`application::Appearance`].
|
|
||||||
fn style(&self, theme: &Theme) -> application::Appearance {
|
|
||||||
use application::DefaultStyle;
|
|
||||||
|
|
||||||
theme.default_style()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the scale factor of the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// It can be used to dynamically control the size of the UI at runtime
|
|
||||||
/// (i.e. zooming).
|
|
||||||
///
|
|
||||||
/// For instance, a scale factor of `2.0` will make widgets twice as big,
|
|
||||||
/// while a scale factor of `0.5` will shrink them to half their size.
|
|
||||||
///
|
|
||||||
/// By default, it returns `1.0`.
|
|
||||||
fn scale_factor(&self) -> f64 {
|
|
||||||
1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs the [`Sandbox`].
|
|
||||||
///
|
|
||||||
/// On native platforms, this method will take control of the current thread
|
|
||||||
/// and __will NOT return__.
|
|
||||||
///
|
|
||||||
/// It should probably be that last thing you call in your `main` function.
|
|
||||||
fn run(settings: Settings<()>) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
Self: 'static + Sized,
|
|
||||||
{
|
|
||||||
<Self as Application>::run(settings)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Application for T
|
|
||||||
where
|
|
||||||
T: Sandbox,
|
|
||||||
{
|
|
||||||
type Executor = iced_futures::backend::null::Executor;
|
|
||||||
type Flags = ();
|
|
||||||
type Message = T::Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<T::Message>) {
|
|
||||||
(T::new(), Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
T::title(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: T::Message) -> Command<T::Message> {
|
|
||||||
T::update(self, message);
|
|
||||||
|
|
||||||
Command::none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, T::Message> {
|
|
||||||
T::view(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn theme(&self) -> Self::Theme {
|
|
||||||
T::theme(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn style(&self, theme: &Theme) -> application::Appearance {
|
|
||||||
T::style(self, theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<T::Message> {
|
|
||||||
Subscription::none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scale_factor(&self) -> f64 {
|
|
||||||
T::scale_factor(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,9 +4,11 @@ use crate::{Font, Pixels};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// The settings of an application.
|
/// The settings of an iced [`Program`].
|
||||||
|
///
|
||||||
|
/// [`Program`]: crate::Program
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Settings<Flags> {
|
pub struct Settings<Flags = ()> {
|
||||||
/// The identifier of the application.
|
/// The identifier of the application.
|
||||||
///
|
///
|
||||||
/// If provided, this identifier may be used to identify the application or
|
/// If provided, this identifier may be used to identify the application or
|
||||||
|
|
@ -18,9 +20,9 @@ pub struct Settings<Flags> {
|
||||||
/// They will be ignored on the Web.
|
/// They will be ignored on the Web.
|
||||||
pub window: window::Settings,
|
pub window: window::Settings,
|
||||||
|
|
||||||
/// The data needed to initialize the [`Application`].
|
/// The data needed to initialize the [`Program`].
|
||||||
///
|
///
|
||||||
/// [`Application`]: crate::Application
|
/// [`Program`]: crate::Program
|
||||||
pub flags: Flags,
|
pub flags: Flags,
|
||||||
|
|
||||||
/// The fonts to load on boot.
|
/// The fonts to load on boot.
|
||||||
|
|
@ -49,9 +51,9 @@ pub struct Settings<Flags> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Flags> Settings<Flags> {
|
impl<Flags> Settings<Flags> {
|
||||||
/// Initialize [`Application`] settings using the given data.
|
/// Initialize [`Program`] settings using the given data.
|
||||||
///
|
///
|
||||||
/// [`Application`]: crate::Application
|
/// [`Program`]: crate::Program
|
||||||
pub fn with_flags(flags: Flags) -> Self {
|
pub fn with_flags(flags: Flags) -> Self {
|
||||||
let default_settings = Settings::<()>::default();
|
let default_settings = Settings::<()>::default();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::core::text::LineHeight;
|
use crate::core::text::LineHeight;
|
||||||
use crate::core::{Pixels, Point, Rectangle, Size, Transformation, Vector};
|
use crate::core::{
|
||||||
|
Pixels, Point, Radians, Rectangle, Size, Transformation, Vector,
|
||||||
|
};
|
||||||
use crate::graphics::geometry::fill::{self, Fill};
|
use crate::graphics::geometry::fill::{self, Fill};
|
||||||
use crate::graphics::geometry::stroke::{self, Stroke};
|
use crate::graphics::geometry::stroke::{self, Stroke};
|
||||||
use crate::graphics::geometry::{Path, Style, Text};
|
use crate::graphics::geometry::{Path, Style, Text};
|
||||||
|
|
@ -192,10 +194,10 @@ impl Frame {
|
||||||
self.transform.pre_translate(translation.x, translation.y);
|
self.transform.pre_translate(translation.x, translation.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rotate(&mut self, angle: f32) {
|
pub fn rotate(&mut self, angle: impl Into<Radians>) {
|
||||||
self.transform = self
|
self.transform = self.transform.pre_concat(
|
||||||
.transform
|
tiny_skia::Transform::from_rotate(angle.into().0.to_degrees()),
|
||||||
.pre_concat(tiny_skia::Transform::from_rotate(angle.to_degrees()));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(&mut self, scale: impl Into<f32>) {
|
pub fn scale(&mut self, scale: impl Into<f32>) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
//! Build and draw geometry.
|
//! Build and draw geometry.
|
||||||
use crate::core::text::LineHeight;
|
use crate::core::text::LineHeight;
|
||||||
use crate::core::{Pixels, Point, Rectangle, Size, Transformation, Vector};
|
use crate::core::{
|
||||||
|
Pixels, Point, Radians, Rectangle, Size, Transformation, Vector,
|
||||||
|
};
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::geometry::fill::{self, Fill};
|
use crate::graphics::geometry::fill::{self, Fill};
|
||||||
use crate::graphics::geometry::{
|
use crate::graphics::geometry::{
|
||||||
|
|
@ -475,12 +477,12 @@ impl Frame {
|
||||||
|
|
||||||
/// Applies a rotation in radians to the current transform of the [`Frame`].
|
/// Applies a rotation in radians to the current transform of the [`Frame`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotate(&mut self, angle: f32) {
|
pub fn rotate(&mut self, angle: impl Into<Radians>) {
|
||||||
self.transforms.current.0 = self
|
self.transforms.current.0 = self
|
||||||
.transforms
|
.transforms
|
||||||
.current
|
.current
|
||||||
.0
|
.0
|
||||||
.pre_rotate(lyon::math::Angle::radians(angle));
|
.pre_rotate(lyon::math::Angle::radians(angle.into().0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a uniform scaling to the current transform of the [`Frame`].
|
/// Applies a uniform scaling to the current transform of the [`Frame`].
|
||||||
|
|
|
||||||
|
|
@ -273,11 +273,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The position of the tooltip. Defaults to following the cursor.
|
/// The position of the tooltip. Defaults to following the cursor.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum Position {
|
pub enum Position {
|
||||||
/// The tooltip will follow the cursor.
|
|
||||||
FollowCursor,
|
|
||||||
/// The tooltip will appear on the top of the widget.
|
/// The tooltip will appear on the top of the widget.
|
||||||
|
#[default]
|
||||||
Top,
|
Top,
|
||||||
/// The tooltip will appear on the bottom of the widget.
|
/// The tooltip will appear on the bottom of the widget.
|
||||||
Bottom,
|
Bottom,
|
||||||
|
|
@ -285,6 +284,8 @@ pub enum Position {
|
||||||
Left,
|
Left,
|
||||||
/// The tooltip will appear on the right of the widget.
|
/// The tooltip will appear on the right of the widget.
|
||||||
Right,
|
Right,
|
||||||
|
/// The tooltip will follow the cursor.
|
||||||
|
FollowCursor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue