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
177
178
179
180
|
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 delightful 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, _macro-free_ API
* Responsive, flexbox-based layouting
* Type-safe, reactive programming model
* Built-in widgets: buttons, checkboxes, radios...
* 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
Iced is heavily inspired by [Elm] and [The Elm Architecture].
Basically, 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__
Let's say we want to build an interactive counter that can be incremented and
decremented using two different buttons.
We start by modelling the __state__ of our application:
```rust
use iced::button;
struct Counter {
// The counter value
value: i32,
// Local state of the two buttons
increment_button: button::State,
decrement_button: button::State,
}
```
Simple enough! 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,
}
```
Now, let's put it all together in our __view logic__:
```rust
use iced::{Button, Column, Text};
impl Counter {
fn view(&mut self) -> Column<Message> {
// 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 it! 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 representing user interactions and produce __messages__ for
our __update logic__.
1. Draw the resulting user interface using our own custom __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 part of [Coffee], my own 2D game engine, as
an attempt at bringing the simplicity of [Elm] and [The Elm Architecture] into
Rust.
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
|