commit
503a48e899
47 changed files with 1298 additions and 892 deletions
25
README.md
25
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),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,8 +160,15 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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::sandbox("Arc - Iced", Arc::update, Arc::view)
|
||||||
antialiasing: true,
|
.subscription(Arc::subscription)
|
||||||
..Settings::default()
|
.theme(|_| Theme::Dark)
|
||||||
})
|
.antialiased()
|
||||||
|
.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::sandbox("Bezier Tool - Iced", Example::update, Example::view)
|
||||||
antialiasing: true,
|
.antialiased()
|
||||||
..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::sandbox("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::sandbox("Clock - Iced", Clock::update, Clock::view)
|
||||||
antialiasing: true,
|
.subscription(Clock::subscription)
|
||||||
..Settings::default()
|
.theme(Clock::theme)
|
||||||
})
|
.antialiased()
|
||||||
|
.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 / 60) % 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(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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: 15.into(),
|
||||||
|
position: Point::new(
|
||||||
|
(0.8 * radius - 8.0) * rotate_factor,
|
||||||
|
-8.0,
|
||||||
|
),
|
||||||
|
color: palette.primary.weak.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,8 +3,8 @@ 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::{
|
use palette::{
|
||||||
self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue,
|
self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue,
|
||||||
|
|
@ -13,11 +13,15 @@ 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::sandbox(
|
||||||
antialiasing: true,
|
"Color Palette - Iced",
|
||||||
default_font: Font::MONOSPACE,
|
ColorPalette::update,
|
||||||
..Settings::default()
|
ColorPalette::view,
|
||||||
})
|
)
|
||||||
|
.theme(ColorPalette::theme)
|
||||||
|
.default_font(Font::MONOSPACE)
|
||||||
|
.antialiased()
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -41,17 +45,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::sandbox("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::sandbox("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,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::application("Events - Iced", Events::update, Events::view)
|
||||||
window: window::Settings {
|
.subscription(Events::subscription)
|
||||||
exit_on_close_request: false,
|
.ignore_close_request()
|
||||||
..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::application("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),
|
||||||
|
|
|
||||||
|
|
@ -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", |_, _| {}, 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,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::sandbox(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::sandbox(
|
||||||
antialiasing: true,
|
"Loading Spinners - Iced",
|
||||||
..Default::default()
|
LoadingSpinners::update,
|
||||||
})
|
LoadingSpinners::view,
|
||||||
|
)
|
||||||
|
.antialiased()
|
||||||
|
.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),
|
||||||
|
|
|
||||||
|
|
@ -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::sandbox("Multitouch - Iced", Multitouch::update, Multitouch::view)
|
||||||
antialiasing: true,
|
.antialiased()
|
||||||
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::sandbox("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::application(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::sandbox(
|
||||||
|
"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::application("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::application(
|
||||||
|
"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::sandbox(
|
||||||
antialiasing: true,
|
"Sierpinski Triangle - Iced",
|
||||||
..Settings::default()
|
SierpinskiEmulator::update,
|
||||||
})
|
SierpinskiEmulator::view,
|
||||||
|
)
|
||||||
|
.antialiased()
|
||||||
|
.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::sandbox(
|
||||||
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::sandbox("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::sandbox("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,23 @@
|
||||||
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::application(
|
||||||
|
"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 +27,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 +44,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,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,7 +16,9 @@ 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::sandbox(Tour::title, Tour::update, Tour::view)
|
||||||
|
.centered()
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tour {
|
pub struct Tour {
|
||||||
|
|
@ -24,11 +26,9 @@ pub struct Tour {
|
||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Tour {
|
impl Tour {
|
||||||
type Message = Message;
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
fn new() -> Tour {
|
|
||||||
Tour {
|
|
||||||
steps: Steps::new(),
|
steps: Steps::new(),
|
||||||
debug: false,
|
debug: false,
|
||||||
}
|
}
|
||||||
|
|
@ -90,6 +90,12 @@ impl Sandbox for Tour {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Tour {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
BackPressed,
|
BackPressed,
|
||||||
|
|
|
||||||
|
|
@ -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::sandbox("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::sandbox(
|
||||||
antialiasing: true,
|
"Vectorial Text - Iced",
|
||||||
..Settings::default()
|
VectorialText::update,
|
||||||
})
|
VectorialText::view,
|
||||||
|
)
|
||||||
|
.theme(|_| Theme::Dark)
|
||||||
|
.antialiased()
|
||||||
|
.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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
src/lib.rs
48
src/lib.rs
|
|
@ -175,6 +175,7 @@ mod error;
|
||||||
mod sandbox;
|
mod sandbox;
|
||||||
|
|
||||||
pub mod application;
|
pub mod application;
|
||||||
|
pub mod program;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
@ -308,6 +309,7 @@ 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 sandbox::Sandbox;
|
||||||
pub use settings::Settings;
|
pub use settings::Settings;
|
||||||
|
|
@ -327,3 +329,49 @@ pub type Element<
|
||||||
///
|
///
|
||||||
/// [`Application`]: crate::Application
|
/// [`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 window title,
|
||||||
|
/// - its update logic,
|
||||||
|
/// - and its view logic.
|
||||||
|
///
|
||||||
|
/// # 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>(
|
||||||
|
title: impl program::Title<State> + 'static,
|
||||||
|
update: impl Fn(&mut State, Message) + 'static,
|
||||||
|
view: impl for<'a> program::View<'a, State, Message> + 'static,
|
||||||
|
) -> Result
|
||||||
|
where
|
||||||
|
State: Default + 'static,
|
||||||
|
Message: std::fmt::Debug + Send + 'static,
|
||||||
|
{
|
||||||
|
sandbox(title, update, view).run()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use program::{application, sandbox};
|
||||||
|
|
|
||||||
732
src/program.rs
Normal file
732
src/program.rs
Normal file
|
|
@ -0,0 +1,732 @@
|
||||||
|
//! Create iced applications out of simple functions.
|
||||||
|
//!
|
||||||
|
//! 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.
|
||||||
|
//!
|
||||||
|
//! This API is meant to be a more convenient—although less
|
||||||
|
//! powerful—alternative to the [`Sandbox`] and [`Application`] traits.
|
||||||
|
//!
|
||||||
|
//! [`Sandbox`]: crate::Sandbox
|
||||||
|
//!
|
||||||
|
//! # Example
|
||||||
|
//! ```no_run
|
||||||
|
//! use iced::widget::{button, column, text, Column};
|
||||||
|
//! use iced::Theme;
|
||||||
|
//!
|
||||||
|
//! pub fn main() -> iced::Result {
|
||||||
|
//! iced::sandbox("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::{self, Application};
|
||||||
|
use crate::executor::{self, Executor};
|
||||||
|
use crate::window;
|
||||||
|
use crate::{Command, Element, Font, Result, Settings, Subscription};
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
/// Creates the most basic kind of [`Program`] from some update and view logic.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```no_run
|
||||||
|
/// use iced::widget::{button, column, text, Column};
|
||||||
|
///
|
||||||
|
/// pub fn main() -> iced::Result {
|
||||||
|
/// iced::sandbox("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 sandbox<State, Message>(
|
||||||
|
title: impl Title<State>,
|
||||||
|
update: impl Fn(&mut State, Message),
|
||||||
|
view: impl for<'a> self::View<'a, State, Message>,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = State, Message = Message, Theme = crate::Theme>,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
State: Default + 'static,
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct Sandbox<State, Message, Update, View> {
|
||||||
|
update: Update,
|
||||||
|
view: View,
|
||||||
|
_state: PhantomData<State>,
|
||||||
|
_message: PhantomData<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State, Message, Update, View> Definition
|
||||||
|
for Sandbox<State, Message, Update, View>
|
||||||
|
where
|
||||||
|
State: Default + 'static,
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
Update: Fn(&mut State, Message),
|
||||||
|
View: for<'a> self::View<'a, State, Message>,
|
||||||
|
{
|
||||||
|
type State = State;
|
||||||
|
type Message = Message;
|
||||||
|
type Theme = crate::Theme;
|
||||||
|
type Executor = iced_futures::backend::null::Executor;
|
||||||
|
|
||||||
|
fn build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
(State::default(), Command::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
(self.update)(state, message);
|
||||||
|
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view<'a>(
|
||||||
|
&self,
|
||||||
|
state: &'a Self::State,
|
||||||
|
) -> Element<'a, Self::Message, Self::Theme> {
|
||||||
|
self.view.view(state).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Program {
|
||||||
|
raw: Sandbox {
|
||||||
|
update,
|
||||||
|
view,
|
||||||
|
_state: PhantomData,
|
||||||
|
_message: PhantomData,
|
||||||
|
},
|
||||||
|
settings: Settings::default(),
|
||||||
|
}
|
||||||
|
.title(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [`Program`] that can leverage the [`Command`] API for
|
||||||
|
/// concurrent operations.
|
||||||
|
pub fn application<State, Message>(
|
||||||
|
title: impl Title<State>,
|
||||||
|
update: impl Fn(&mut State, Message) -> Command<Message>,
|
||||||
|
view: impl for<'a> self::View<'a, State, Message>,
|
||||||
|
) -> Program<
|
||||||
|
impl Definition<State = State, Message = Message, Theme = crate::Theme>,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
State: Default + 'static,
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct Application<State, Message, Update, View> {
|
||||||
|
update: Update,
|
||||||
|
view: View,
|
||||||
|
_state: PhantomData<State>,
|
||||||
|
_message: PhantomData<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State, Message, Update, View> Definition
|
||||||
|
for Application<State, Message, Update, View>
|
||||||
|
where
|
||||||
|
State: Default,
|
||||||
|
Message: Send + std::fmt::Debug,
|
||||||
|
Update: Fn(&mut State, Message) -> Command<Message>,
|
||||||
|
View: for<'a> self::View<'a, State, Message>,
|
||||||
|
{
|
||||||
|
type State = State;
|
||||||
|
type Message = Message;
|
||||||
|
type Theme = crate::Theme;
|
||||||
|
type Executor = executor::Default;
|
||||||
|
|
||||||
|
fn build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
(Self::State::default(), Command::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
state: &mut Self::State,
|
||||||
|
message: Self::Message,
|
||||||
|
) -> Command<Self::Message> {
|
||||||
|
(self.update)(state, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
settings: Settings::default(),
|
||||||
|
}
|
||||||
|
.title(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A fully functioning and configured iced application.
|
||||||
|
///
|
||||||
|
/// It can be [`run`]!
|
||||||
|
///
|
||||||
|
/// Create one with either the [`sandbox`] or [`application`] helpers.
|
||||||
|
///
|
||||||
|
/// [`run`]: Program::run
|
||||||
|
/// [`application`]: self::application()
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Program<P: Definition> {
|
||||||
|
raw: P,
|
||||||
|
settings: Settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition> Program<P> {
|
||||||
|
/// Runs the [`Program`].
|
||||||
|
pub fn run(self) -> Result
|
||||||
|
where
|
||||||
|
Self: 'static,
|
||||||
|
{
|
||||||
|
struct Instance<P: Definition> {
|
||||||
|
program: P,
|
||||||
|
state: P::State,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Definition> Application for Instance<P> {
|
||||||
|
type Message = P::Message;
|
||||||
|
type Theme = P::Theme;
|
||||||
|
type Flags = P;
|
||||||
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn new(program: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||||
|
let (state, command) = P::build(&program);
|
||||||
|
|
||||||
|
(Self { program, state }, 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 theme(&self) -> Self::Theme {
|
||||||
|
self.program.theme(&self.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(&self) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(&self.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self { raw, settings } = self;
|
||||||
|
|
||||||
|
Instance::run(Settings {
|
||||||
|
flags: raw,
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Toggles the [`Settings::antialiasing`] to `true` for the [`Program`].
|
||||||
|
pub fn antialiased(self) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
antialiasing: true,
|
||||||
|
..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`] to `false` in the [`Program`].
|
||||||
|
pub fn ignore_close_request(self) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: Settings {
|
||||||
|
window: window::Settings {
|
||||||
|
exit_on_close_request: false,
|
||||||
|
..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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The internal definition of a [`Program`].
|
||||||
|
///
|
||||||
|
/// You should not need to implement this trait directly. Instead, use the
|
||||||
|
/// helper functions available in the [`program`] module and the [`Program`] struct.
|
||||||
|
///
|
||||||
|
/// [`program`]: crate::program
|
||||||
|
#[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 + application::DefaultStyle;
|
||||||
|
|
||||||
|
/// The executor of the program.
|
||||||
|
type Executor: Executor;
|
||||||
|
|
||||||
|
fn build(&self) -> (Self::State, 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 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 build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
self.program.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
let (state, command) = self.program.build();
|
||||||
|
|
||||||
|
(state, Command::batch([command, (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 theme(&self, state: &Self::State) -> Self::Theme {
|
||||||
|
self.program.theme(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(
|
||||||
|
&self,
|
||||||
|
state: &Self::State,
|
||||||
|
) -> Subscription<Self::Message> {
|
||||||
|
self.program.subscription(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
self.program.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 build(&self) -> (Self::State, Command<Self::Message>) {
|
||||||
|
self.program.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithTheme { program, theme: f }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The title logic of some [`Program`].
|
||||||
|
///
|
||||||
|
/// This trait is implemented both for `&static str` and
|
||||||
|
/// any closure `Fn(&State) -> String`.
|
||||||
|
///
|
||||||
|
/// You can use any of these in [`Program::title`].
|
||||||
|
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 view logic of some [`Program`].
|
||||||
|
///
|
||||||
|
/// This trait allows [`sandbox`] and [`application`] to
|
||||||
|
/// take any closure that returns any `Into<Element<'_, Message>>`.
|
||||||
|
///
|
||||||
|
/// [`application`]: self::application()
|
||||||
|
pub trait View<'a, State, Message> {
|
||||||
|
/// The widget returned by the view logic.
|
||||||
|
type Widget: Into<Element<'a, Message>>;
|
||||||
|
|
||||||
|
/// Produces the widget of the [`Program`].
|
||||||
|
fn view(&self, state: &'a State) -> Self::Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T, State, Message, Widget> View<'a, State, Message> for T
|
||||||
|
where
|
||||||
|
T: Fn(&'a State) -> Widget,
|
||||||
|
State: 'static,
|
||||||
|
Widget: Into<Element<'a, Message>>,
|
||||||
|
{
|
||||||
|
type Widget = Widget;
|
||||||
|
|
||||||
|
fn view(&self, state: &'a State) -> Self::Widget {
|
||||||
|
self(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
/// The settings of an application.
|
/// The settings of an application.
|
||||||
#[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
|
||||||
|
|
|
||||||
|
|
@ -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