iced/lib.rs
1//! iced is a cross-platform GUI library focused on simplicity and type-safety.
2//! Inspired by [Elm].
3//!
4//! [Elm]: https://elm-lang.org/
5//!
6//! # Disclaimer
7//! iced is __experimental__ software. If you expect the documentation to hold your hand
8//! as you learn the ropes, you are in for a frustrating experience.
9//!
10//! The library leverages Rust to its full extent: ownership, borrowing, lifetimes, futures,
11//! streams, first-class functions, trait bounds, closures, and more. This documentation
12//! is not meant to teach you any of these. Far from it, it will assume you have __mastered__
13//! all of them.
14//!
15//! Furthermore—just like Rust—iced is very unforgiving. It will not let you easily cut corners.
16//! The type signatures alone can be used to learn how to use most of the library.
17//! Everything is connected.
18//!
19//! Therefore, iced is easy to learn for __advanced__ Rust programmers; but plenty of patient
20//! beginners have learned it and had a good time with it. Since it leverages a lot of what
21//! Rust has to offer in a type-safe way, it can be a great way to discover Rust itself.
22//!
23//! If you don't like the sound of that, you expect to be spoonfed, or you feel frustrated
24//! and struggle to use the library; then I recommend you to wait patiently until [the book]
25//! is finished.
26//!
27//! [the book]: https://book.iced.rs
28//!
29//! # The Pocket Guide
30//! Start by calling [`run`]:
31//!
32//! ```rust,no_run
33//! pub fn main() -> iced::Result {
34//! iced::run("A cool counter", update, view)
35//! }
36//! # fn update(state: &mut (), message: ()) {}
37//! # fn view(state: &()) -> iced::Element<()> { iced::widget::text("").into() }
38//! ```
39//!
40//! Define an `update` function to __change__ your state:
41//!
42//! ```rust
43//! fn update(counter: &mut u64, message: Message) {
44//! match message {
45//! Message::Increment => *counter += 1,
46//! }
47//! }
48//! # #[derive(Clone)]
49//! # enum Message { Increment }
50//! ```
51//!
52//! Define a `view` function to __display__ your state:
53//!
54//! ```rust
55//! use iced::widget::{button, text};
56//! use iced::Element;
57//!
58//! fn view(counter: &u64) -> Element<Message> {
59//! button(text(counter)).on_press(Message::Increment).into()
60//! }
61//! # #[derive(Clone)]
62//! # enum Message { Increment }
63//! ```
64//!
65//! And create a `Message` enum to __connect__ `view` and `update` together:
66//!
67//! ```rust
68//! #[derive(Debug, Clone)]
69//! enum Message {
70//! Increment,
71//! }
72//! ```
73//!
74//! ## Custom State
75//! You can define your own struct for your state:
76//!
77//! ```rust
78//! #[derive(Default)]
79//! struct Counter {
80//! value: u64,
81//! }
82//! ```
83//!
84//! But you have to change `update` and `view` accordingly:
85//!
86//! ```rust
87//! # struct Counter { value: u64 }
88//! # #[derive(Clone)]
89//! # enum Message { Increment }
90//! # use iced::widget::{button, text};
91//! # use iced::Element;
92//! fn update(counter: &mut Counter, message: Message) {
93//! match message {
94//! Message::Increment => counter.value += 1,
95//! }
96//! }
97//!
98//! fn view(counter: &Counter) -> Element<Message> {
99//! button(text(counter.value)).on_press(Message::Increment).into()
100//! }
101//! ```
102//!
103//! ## Widgets and Elements
104//! The `view` function must return an [`Element`]. An [`Element`] is just a generic [`widget`].
105//!
106//! The [`widget`] module contains a bunch of functions to help you build
107//! and use widgets.
108//!
109//! Widgets are configured using the builder pattern:
110//!
111//! ```rust
112//! # struct Counter { value: u64 }
113//! # #[derive(Clone)]
114//! # enum Message { Increment }
115//! use iced::widget::{button, column, text};
116//! use iced::Element;
117//!
118//! fn view(counter: &Counter) -> Element<Message> {
119//! column![
120//! text(counter.value).size(20),
121//! button("Increment").on_press(Message::Increment),
122//! ]
123//! .spacing(10)
124//! .into()
125//! }
126//! ```
127//!
128//! A widget can be turned into an [`Element`] by calling `into`.
129//!
130//! Widgets and elements are generic over the message type they produce. The
131//! [`Element`] returned by `view` must have the same `Message` type as
132//! your `update`.
133//!
134//! ## Layout
135//! There is no unified layout system in iced. Instead, each widget implements
136//! its own layout strategy.
137//!
138//! Building your layout will often consist in using a combination of
139//! [rows], [columns], and [containers]:
140//!
141//! ```rust
142//! # struct State;
143//! # enum Message {}
144//! use iced::widget::{column, container, row};
145//! use iced::{Fill, Element};
146//!
147//! fn view(state: &State) -> Element<Message> {
148//! container(
149//! column![
150//! "Top",
151//! row!["Left", "Right"].spacing(10),
152//! "Bottom"
153//! ]
154//! .spacing(10)
155//! )
156//! .padding(10)
157//! .center_x(Fill)
158//! .center_y(Fill)
159//! .into()
160//! }
161//! ```
162//!
163//! Rows and columns lay out their children horizontally and vertically,
164//! respectively. [Spacing] can be easily added between elements.
165//!
166//! Containers position or align a single widget inside their bounds.
167//!
168//! [rows]: widget::Row
169//! [columns]: widget::Column
170//! [containers]: widget::Container
171//! [Spacing]: widget::Column::spacing
172//!
173//! ## Sizing
174//! The width and height of widgets can generally be defined using a [`Length`].
175//!
176//! - [`Fill`] will make the widget take all the available space in a given axis.
177//! - [`Shrink`] will make the widget use its intrinsic size.
178//!
179//! Most widgets use a [`Shrink`] sizing strategy by default, but will inherit
180//! a [`Fill`] strategy from their children.
181//!
182//! A fixed numeric [`Length`] in [`Pixels`] can also be used:
183//!
184//! ```rust
185//! # struct State;
186//! # enum Message {}
187//! use iced::widget::container;
188//! use iced::Element;
189//!
190//! fn view(state: &State) -> Element<Message> {
191//! container("I am 300px tall!").height(300).into()
192//! }
193//! ```
194//!
195//! ## Theming
196//! The default [`Theme`] of an application can be changed by defining a `theme`
197//! function and leveraging the [`Application`] builder, instead of directly
198//! calling [`run`]:
199//!
200//! ```rust,no_run
201//! # #[derive(Default)]
202//! # struct State;
203//! use iced::Theme;
204//!
205//! pub fn main() -> iced::Result {
206//! iced::application("A cool application", update, view)
207//! .theme(theme)
208//! .run()
209//! }
210//!
211//! fn theme(state: &State) -> Theme {
212//! Theme::TokyoNight
213//! }
214//! # fn update(state: &mut State, message: ()) {}
215//! # fn view(state: &State) -> iced::Element<()> { iced::widget::text("").into() }
216//! ```
217//!
218//! The `theme` function takes the current state of the application, allowing the
219//! returned [`Theme`] to be completely dynamic—just like `view`.
220//!
221//! There are a bunch of built-in [`Theme`] variants at your disposal, but you can
222//! also [create your own](Theme::custom).
223//!
224//! ## Styling
225//! As with layout, iced does not have a unified styling system. However, all
226//! of the built-in widgets follow the same styling approach.
227//!
228//! The appearance of a widget can be changed by calling its `style` method:
229//!
230//! ```rust
231//! # struct State;
232//! # enum Message {}
233//! use iced::widget::container;
234//! use iced::Element;
235//!
236//! fn view(state: &State) -> Element<Message> {
237//! container("I am a rounded box!").style(container::rounded_box).into()
238//! }
239//! ```
240//!
241//! The `style` method of a widget takes a closure that, given the current active
242//! [`Theme`], returns the widget style:
243//!
244//! ```rust
245//! # struct State;
246//! # #[derive(Clone)]
247//! # enum Message {}
248//! use iced::widget::button;
249//! use iced::{Element, Theme};
250//!
251//! fn view(state: &State) -> Element<Message> {
252//! button("I am a styled button!").style(|theme: &Theme, status| {
253//! let palette = theme.extended_palette();
254//!
255//! match status {
256//! button::Status::Active => {
257//! button::Style::default()
258//! .with_background(palette.success.strong.color)
259//! }
260//! _ => button::primary(theme, status),
261//! }
262//! })
263//! .into()
264//! }
265//! ```
266//!
267//! Widgets that can be in multiple different states will also provide the closure
268//! with some [`Status`], allowing you to use a different style for each state.
269//!
270//! You can extract the [`Palette`] colors of a [`Theme`] with the [`palette`] or
271//! [`extended_palette`] methods.
272//!
273//! Most widgets provide styling functions for your convenience in their respective modules;
274//! like [`container::rounded_box`], [`button::primary`], or [`text::danger`].
275//!
276//! [`Status`]: widget::button::Status
277//! [`palette`]: Theme::palette
278//! [`extended_palette`]: Theme::extended_palette
279//! [`container::rounded_box`]: widget::container::rounded_box
280//! [`button::primary`]: widget::button::primary
281//! [`text::danger`]: widget::text::danger
282//!
283//! ## Concurrent Tasks
284//! The `update` function can _optionally_ return a [`Task`].
285//!
286//! A [`Task`] can be leveraged to perform asynchronous work, like running a
287//! future or a stream:
288//!
289//! ```rust
290//! # #[derive(Clone)]
291//! # struct Weather;
292//! use iced::Task;
293//!
294//! struct State {
295//! weather: Option<Weather>,
296//! }
297//!
298//! enum Message {
299//! FetchWeather,
300//! WeatherFetched(Weather),
301//! }
302//!
303//! fn update(state: &mut State, message: Message) -> Task<Message> {
304//! match message {
305//! Message::FetchWeather => Task::perform(
306//! fetch_weather(),
307//! Message::WeatherFetched,
308//! ),
309//! Message::WeatherFetched(weather) => {
310//! state.weather = Some(weather);
311//!
312//! Task::none()
313//! }
314//! }
315//! }
316//!
317//! async fn fetch_weather() -> Weather {
318//! // ...
319//! # unimplemented!()
320//! }
321//! ```
322//!
323//! Tasks can also be used to interact with the iced runtime. Some modules
324//! expose functions that create tasks for different purposes—like [changing
325//! window settings](window#functions), [focusing a widget](widget::focus_next), or
326//! [querying its visible bounds](widget::container::visible_bounds).
327//!
328//! Like futures and streams, tasks expose [a monadic interface](Task::then)—but they can also be
329//! [mapped](Task::map), [chained](Task::chain), [batched](Task::batch), [canceled](Task::abortable),
330//! and more.
331//!
332//! ## Passive Subscriptions
333//! Applications can subscribe to passive sources of data—like time ticks or runtime events.
334//!
335//! You will need to define a `subscription` function and use the [`Application`] builder:
336//!
337//! ```rust,no_run
338//! # #[derive(Default)]
339//! # struct State;
340//! use iced::window;
341//! use iced::{Size, Subscription};
342//!
343//! #[derive(Debug)]
344//! enum Message {
345//! WindowResized(Size),
346//! }
347//!
348//! pub fn main() -> iced::Result {
349//! iced::application("A cool application", update, view)
350//! .subscription(subscription)
351//! .run()
352//! }
353//!
354//! fn subscription(state: &State) -> Subscription<Message> {
355//! window::resize_events().map(|(_id, size)| Message::WindowResized(size))
356//! }
357//! # fn update(state: &mut State, message: Message) {}
358//! # fn view(state: &State) -> iced::Element<Message> { iced::widget::text("").into() }
359//! ```
360//!
361//! A [`Subscription`] is [a _declarative_ builder of streams](Subscription#the-lifetime-of-a-subscription)
362//! that are not allowed to end on their own. Only the `subscription` function
363//! dictates the active subscriptions—just like `view` fully dictates the
364//! visible widgets of your user interface, at every moment.
365//!
366//! As with tasks, some modules expose convenient functions that build a [`Subscription`] for you—like
367//! [`time::every`] which can be used to listen to time, or [`keyboard::on_key_press`] which will notify you
368//! of any key presses. But you can also create your own with [`Subscription::run`] and [`run_with_id`].
369//!
370//! [`run_with_id`]: Subscription::run_with_id
371//!
372//! ## Scaling Applications
373//! The `update`, `view`, and `Message` triplet composes very nicely.
374//!
375//! A common pattern is to leverage this composability to split an
376//! application into different screens:
377//!
378//! ```rust
379//! # mod contacts {
380//! # use iced::{Element, Task};
381//! # pub struct Contacts;
382//! # impl Contacts {
383//! # pub fn update(&mut self, message: Message) -> Action { unimplemented!() }
384//! # pub fn view(&self) -> Element<Message> { unimplemented!() }
385//! # }
386//! # #[derive(Debug)]
387//! # pub enum Message {}
388//! # pub enum Action { None, Run(Task<Message>), Chat(()) }
389//! # }
390//! # mod conversation {
391//! # use iced::{Element, Task};
392//! # pub struct Conversation;
393//! # impl Conversation {
394//! # pub fn new(contact: ()) -> (Self, Task<Message>) { unimplemented!() }
395//! # pub fn update(&mut self, message: Message) -> Task<Message> { unimplemented!() }
396//! # pub fn view(&self) -> Element<Message> { unimplemented!() }
397//! # }
398//! # #[derive(Debug)]
399//! # pub enum Message {}
400//! # }
401//! use contacts::Contacts;
402//! use conversation::Conversation;
403//!
404//! use iced::{Element, Task};
405//!
406//! struct State {
407//! screen: Screen,
408//! }
409//!
410//! enum Screen {
411//! Contacts(Contacts),
412//! Conversation(Conversation),
413//! }
414//!
415//! enum Message {
416//! Contacts(contacts::Message),
417//! Conversation(conversation::Message)
418//! }
419//!
420//! fn update(state: &mut State, message: Message) -> Task<Message> {
421//! match message {
422//! Message::Contacts(message) => {
423//! if let Screen::Contacts(contacts) = &mut state.screen {
424//! let action = contacts.update(message);
425//!
426//! match action {
427//! contacts::Action::None => Task::none(),
428//! contacts::Action::Run(task) => task.map(Message::Contacts),
429//! contacts::Action::Chat(contact) => {
430//! let (conversation, task) = Conversation::new(contact);
431//!
432//! state.screen = Screen::Conversation(conversation);
433//!
434//! task.map(Message::Conversation)
435//! }
436//! }
437//! } else {
438//! Task::none()
439//! }
440//! }
441//! Message::Conversation(message) => {
442//! if let Screen::Conversation(conversation) = &mut state.screen {
443//! conversation.update(message).map(Message::Conversation)
444//! } else {
445//! Task::none()
446//! }
447//! }
448//! }
449//! }
450//!
451//! fn view(state: &State) -> Element<Message> {
452//! match &state.screen {
453//! Screen::Contacts(contacts) => contacts.view().map(Message::Contacts),
454//! Screen::Conversation(conversation) => conversation.view().map(Message::Conversation),
455//! }
456//! }
457//! ```
458//!
459//! The `update` method of a screen can return an `Action` enum that can be leveraged by the parent to
460//! execute a task or transition to a completely different screen altogether. The variants of `Action` can
461//! have associated data. For instance, in the example above, the `Conversation` screen is created when
462//! `Contacts::update` returns an `Action::Chat` with the selected contact.
463//!
464//! Effectively, this approach lets you "tell a story" to connect different screens together in a type safe
465//! way.
466//!
467//! Furthermore, functor methods like [`Task::map`], [`Element::map`], and [`Subscription::map`] make composition
468//! seamless.
469#![doc(
470 html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/bdf0430880f5c29443f5f0a0ae4895866dfef4c6/docs/logo.svg"
471)]
472#![cfg_attr(docsrs, feature(doc_auto_cfg))]
473#![cfg_attr(docsrs, feature(doc_cfg))]
474
475// #[cfg(all(feature = "wayland", feature = "winit"))]
476// compile_error!("cannot use `wayland` feature with `winit");
477
478pub use iced_futures::futures;
479pub use iced_futures::stream;
480pub use iced_widget::core;
481use iced_widget::graphics;
482use iced_widget::renderer;
483pub use iced_widget::runtime;
484
485#[cfg(feature = "winit")]
486use iced_winit as shell;
487
488#[cfg(feature = "highlighter")]
489pub use iced_highlighter as highlighter;
490
491#[cfg(feature = "wgpu")]
492pub use iced_renderer::wgpu::wgpu;
493
494mod error;
495pub mod program;
496
497pub mod application;
498pub mod daemon;
499pub mod settings;
500pub mod time;
501pub mod window;
502
503#[cfg(feature = "winit")]
504pub mod platform_specific {
505 pub use iced_winit::{
506 platform_specific as shell, runtime::platform_specific as runtime,
507 };
508}
509
510#[cfg(feature = "winit")]
511pub use application::Application;
512#[cfg(feature = "winit")]
513pub use program::Program;
514
515#[cfg(feature = "advanced")]
516pub mod advanced;
517
518pub use crate::core::alignment;
519pub use crate::core::border::{self, Radius};
520pub use crate::core::color;
521pub use crate::core::gradient;
522pub use crate::core::padding;
523pub use crate::core::theme;
524pub use crate::core::{
525 id, layout::Limits, Alignment, Background, Border, Color, ContentFit,
526 Degrees, Gradient, Length, Padding, Pixels, Point, Radians, Rectangle,
527 Rotation, Shadow, Size, Theme, Transformation, Vector,
528};
529pub use crate::runtime::exit;
530pub use iced_futures::Subscription;
531
532pub use alignment::Horizontal::{Left, Right};
533pub use alignment::Vertical::{Bottom, Top};
534pub use Alignment::Center;
535pub use Length::{Fill, FillPortion, Shrink};
536
537pub mod task {
538 //! Create runtime tasks.
539 pub use crate::runtime::task::{Handle, Task};
540}
541
542pub mod clipboard {
543 //! Access the clipboard.
544 pub use crate::runtime::clipboard::{
545 read, read_data, read_primary, read_primary_data, write, write_data,
546 write_primary, write_primary_data,
547 };
548 pub use dnd;
549 pub use mime;
550}
551
552pub mod executor {
553 //! Choose your preferred executor to power your application.
554 pub use iced_futures::Executor;
555
556 /// A default cross-platform executor.
557 ///
558 /// - On native platforms, it will use:
559 /// - `iced_futures::backend::native::tokio` when the `tokio` feature is enabled.
560 /// - `iced_futures::backend::native::async-std` when the `async-std` feature is
561 /// enabled.
562 /// - `iced_futures::backend::native::smol` when the `smol` feature is enabled.
563 /// - `iced_futures::backend::native::thread_pool` otherwise.
564 ///
565 /// - On Wasm, it will use `iced_futures::backend::wasm::wasm_bindgen`.
566 pub type Default = iced_futures::backend::default::Executor;
567}
568
569pub mod font {
570 //! Load and use fonts.
571 pub use crate::core::font::*;
572 pub use crate::runtime::font::*;
573}
574
575pub mod event {
576 //! Handle events of a user interface.
577 #[cfg(feature = "wayland")]
578 pub use crate::core::event::wayland;
579 pub use crate::core::event::PlatformSpecific;
580 pub use crate::core::event::{Event, Status};
581 pub use iced_futures::event::{listen, listen_raw, listen_with};
582}
583
584pub mod keyboard {
585 //! Listen and react to keyboard events.
586 pub use crate::core::keyboard::key;
587 pub use crate::core::keyboard::{Event, Key, Location, Modifiers};
588 pub use iced_futures::keyboard::{on_key_press, on_key_release};
589}
590
591pub mod mouse {
592 //! Listen and react to mouse events.
593 pub use crate::core::mouse::{
594 Button, Cursor, Event, Interaction, ScrollDelta,
595 };
596}
597
598#[cfg(feature = "system")]
599pub mod system {
600 //! Retrieve system information.
601 pub use crate::runtime::system::Information;
602 #[cfg(any(feature = "winit", feature = "wayland"))]
603 pub use crate::shell::system::*;
604}
605
606pub mod overlay {
607 //! Display interactive elements on top of other widgets.
608
609 /// A generic overlay.
610 ///
611 /// This is an alias of an [`overlay::Element`] with a default `Renderer`.
612 ///
613 /// [`overlay::Element`]: crate::core::overlay::Element
614 pub type Element<
615 'a,
616 Message,
617 Theme = crate::Renderer,
618 Renderer = crate::Renderer,
619 > = crate::core::overlay::Element<'a, Message, Theme, Renderer>;
620
621 pub use iced_widget::overlay::*;
622}
623
624pub mod touch {
625 //! Listen and react to touch events.
626 pub use crate::core::touch::{Event, Finger};
627}
628
629#[allow(hidden_glob_reexports)]
630pub mod widget {
631 //! Use the built-in widgets or create your own.
632 pub use iced_widget::*;
633
634 // We hide the re-exported modules by `iced_widget`
635 mod core {}
636 mod graphics {}
637 mod native {}
638 mod renderer {}
639 mod style {}
640 mod runtime {}
641}
642
643pub use application::application;
644pub use daemon::{daemon, Daemon};
645pub use error::Error;
646pub use event::Event;
647pub use executor::Executor;
648pub use font::Font;
649pub use renderer::Renderer;
650pub use settings::Settings;
651pub use task::Task;
652
653/// A generic widget.
654///
655/// This is an alias of an `iced_native` element with a default `Renderer`.
656pub type Element<
657 'a,
658 Message,
659 Theme = crate::Theme,
660 Renderer = crate::Renderer,
661> = crate::core::Element<'a, Message, Theme, Renderer>;
662
663/// The result of running an iced program.
664pub type Result = std::result::Result<(), Error>;
665
666#[cfg(feature = "winit")]
667/// Runs a basic iced application with default [`Settings`] given its title,
668/// update, and view logic.
669///
670/// This is equivalent to chaining [`application()`] with [`Application::run`].
671///
672/// # Example
673/// ```no_run
674/// use iced::widget::{button, column, text, Column};
675///
676/// pub fn main() -> iced::Result {
677/// iced::run("A counter", update, view)
678/// }
679///
680/// #[derive(Debug, Clone)]
681/// enum Message {
682/// Increment,
683/// }
684///
685/// fn update(value: &mut u64, message: Message) {
686/// match message {
687/// Message::Increment => *value += 1,
688/// }
689/// }
690///
691/// fn view(value: &u64) -> Column<Message> {
692/// column![
693/// text(value),
694/// button("+").on_press(Message::Increment),
695/// ]
696/// }
697/// ```
698pub fn run<State, Message, Theme, Renderer>(
699 title: impl application::Title<State> + 'static,
700 update: impl application::Update<State, Message> + 'static,
701 view: impl for<'a> application::View<'a, State, Message, Theme, Renderer>
702 + 'static,
703) -> Result
704where
705 State: Default + 'static,
706 Message: std::fmt::Debug + Send + 'static,
707 Theme: Default + program::DefaultStyle + 'static,
708 Renderer: program::Renderer + 'static,
709{
710 application(title, update, view).run()
711}