1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# Iced
[](https://travis-ci.org/hecrj/iced)
[](https://docs.rs/iced)
[](https://crates.io/crates/iced)
[](https://github.com/hecrj/iced/blob/master/LICENSE)
A simple GUI runtime for Rust, heavily inspired by [Elm].
__Iced is in a very early stage of development.__ Many [basic features are still
missing] and there are probably _many_ bugs. [Feel free to contribute!]
[basic features are still missing]: https://github.com/hecrj/iced/issues?q=is%3Aissue+is%3Aopen+label%3Afeature
[Feel free to contribute!]: #contributing--feedback
[![UI Tour - Coffee][gui_gif]][gui_gfycat]
[gui_gif]: https://thumbs.gfycat.com/GloomyWeakHammerheadshark-small.gif
[gui_gfycat]: https://gfycat.com/gloomyweakhammerheadshark
## Features
* Simple, easy-to-use API
* Responsive, flexbox-based layouting
* Type-safe, reactive programming model
* Built-in widgets
* Custom widget support
* Renderer-agnostic runtime
## Installation
Add `iced` as a dependency in your `Cargo.toml`:
```toml
iced = "0.1"
```
__Iced moves fast and the `master` branch can contain breaking changes!__ If
you want to learn about a specific release, check out [the release list].
[the release list]: https://github.com/hecrj/iced/releases
## Overview
Inspired by [The Elm Architecture], Iced expects you to split user interfaces
into four different concepts:
* __State__ — the state of your application
* __Messages__ — user interactions or meaningful events that you care
about
* __View logic__ — a way to display your __state__ as widgets that
may produce __messages__ on user interaction
* __Update logic__ — a way to react to __messages__ and update your
__state__
We can build something to see how this works! Let's say we want a simple counter
that can be incremented and decremented using two buttons.
We start by modelling the __state__ of our application:
```rust
use iced::button;
struct Counter {
// The counter value
value: i32,
// The local state of the two buttons
increment_button: button::State,
decrement_button: button::State,
}
```
Now that we have state, what are the user interactions we care about? The
button presses! These are our __messages__:
```rust
#[derive(Debug, Clone, Copy)]
pub enum Message {
IncrementPressed,
DecrementPressed,
}
```
Next, let's put it all together in our __view logic__:
```rust
use iced::{Button, Column, Text};
use iced_wgpu::Renderer; // Iced is renderer-agnostic! We need to bring our own!
impl Counter {
fn view(&mut self) -> Column<Message, Renderer> {
// We use a column: a simple vertical layout
Column::new()
.push(
// The increment button. We tell it to produce an
// `IncrementPressed` message when pressed
Button::new(&mut self.increment_button, "+")
.on_press(Message::IncrementPressed),
)
.push(
// We show the value of the counter here
Text::new(&self.value.to_string()).size(50),
)
.push(
// The decrement button. We tell it to produce a
// `DecrementPressed` message when pressed
Button::new(&mut self.decrement_button, "-")
.on_press(Message::DecrementPressed),
)
}
}
```
Finally, we need to be able to react to the __messages__ and mutate our
__state__ accordingly in our __update logic__:
```rust
impl Counter {
// ...
fn update(&mut self, message: Message) {
match message {
Message::IncrementPressed => {
self.value += 1;
}
Message::DecrementPressed => {
self.value -= 1;
}
}
}
}
```
And that's everything! We just wrote a whole user interface. Iced is now able
to:
1. Take the result of our __view logic__ and build a user interface.
1. Process events from our system and produce __messages__ for our
__update logic__.
1. Draw the resulting user interface using our chosen __renderer__.
Browse the [documentation] and the [examples] to learn more!
[documentation]: https://docs.rs/iced
[examples]: https://github.com/hecrj/iced/tree/master/examples
## Gallery
[![UI Tour - Coffee][gui_gif]][gui_gfycat]
[gui_gif]: https://thumbs.gfycat.com/GloomyWeakHammerheadshark-small.gif
[gui_gfycat]: https://gfycat.com/gloomyweakhammerheadshark
## Implementation details
Iced was originally born as an attempt at bringing the simplicity of [Elm] and
[The Elm Architecture] into [Coffee], a 2D game engine I am working on.
Currently, Iced builds upon
* [`stretch`] for flexbox-based layouting.
* [`nalgebra`] for the `Point` type.
[`stretch`]: https://github.com/vislyhq/stretch
[`nalgebra`]: https://github.com/rustsim/nalgebra
[Coffee]: https://github.com/hecrj/coffee
[Elm]: https://elm-lang.org/
[The Elm Architecture]: https://guide.elm-lang.org/architecture/
## Contributing / Feedback
If you want to contribute, you are more than welcome to be a part of the
project! Check out the current [issues] if you want to find something to work
on. Try to share you thoughts first! Feel free to open a new issue if you want
to discuss new ideas.
Any kind of feedback is welcome! You can open an issue or, if you want to talk,
you can find me (and a bunch of awesome folks) over the `#gui-and-ui` channel in
the [Rust Community Discord]. I go by `@lone_scientist` there.
[issues]: https://github.com/hecrj/iced/issues
[Rust Community Discord]: https://bit.ly/rust-community
|