summaryrefslogtreecommitdiffstats
path: root/src/pure
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-05-04 17:19:28 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-05-04 17:19:28 +0200
commit27fdc707562d4e229f07ed9496ed5d64f4e108bc (patch)
tree8a87286f0ccd125df1c2b5c597c2d2805ceb27c5 /src/pure
parenta97c520c814a6d3cc538537791be39e0c3182d6d (diff)
parent02914e5e68d1fbaad53483cd32c74d9ac448d1eb (diff)
downloadiced-27fdc707562d4e229f07ed9496ed5d64f4e108bc.tar.gz
iced-27fdc707562d4e229f07ed9496ed5d64f4e108bc.tar.bz2
iced-27fdc707562d4e229f07ed9496ed5d64f4e108bc.zip
Merge branch 'master' into dev/system-information
Diffstat (limited to '')
-rw-r--r--src/pure.rs79
-rw-r--r--src/pure/widget.rs12
2 files changed, 90 insertions, 1 deletions
diff --git a/src/pure.rs b/src/pure.rs
index 948183f1..7785a104 100644
--- a/src/pure.rs
+++ b/src/pure.rs
@@ -14,6 +14,84 @@
//! offers an alternate [`Application`] trait with a completely pure `view`
//! method.
//!
+//! # The Elm Architecture, purity, and continuity
+//! As you may know, applications made with `iced` use [The Elm Architecture].
+//!
+//! In a nutshell, this architecture defines the initial state of the application, a way to `view` it, and a way to `update` it after a user interaction. The `update` logic is called after a meaningful user interaction, which in turn updates the state of the application. Then, the `view` logic is executed to redisplay the application.
+//!
+//! Since `view` logic is only run after an `update`, all of the mutations to the application state must only happen in the `update` logic. If the application state changes anywhere else, the `view` logic will not be rerun and, therefore, the previously generated `view` may stay outdated.
+//!
+//! However, the `Application` trait in `iced` defines `view` as:
+//!
+//! ```ignore
+//! pub trait Application {
+//! fn view(&mut self) -> Element<Self::Message>;
+//! }
+//! ```
+//!
+//! As a consequence, the application state can be mutated in `view` logic. The `view` logic in `iced` is __impure__.
+//!
+//! This impurity is necessary because `iced` puts the burden of widget __continuity__ on its users. In other words, it's up to you to provide `iced` with the internal state of each widget every time `view` is called.
+//!
+//! If we take a look at the classic `counter` example:
+//!
+//! ```ignore
+//! struct Counter {
+//! value: i32,
+//! increment_button: button::State,
+//! decrement_button: button::State,
+//! }
+//!
+//! // ...
+//!
+//! impl Counter {
+//! pub fn view(&mut self) -> Column<Message> {
+//! Column::new()
+//! .push(
+//! Button::new(&mut self.increment_button, Text::new("+"))
+//! .on_press(Message::IncrementPressed),
+//! )
+//! .push(Text::new(self.value.to_string()).size(50))
+//! .push(
+//! Button::new(&mut self.decrement_button, Text::new("-"))
+//! .on_press(Message::DecrementPressed),
+//! )
+//! }
+//! }
+//! ```
+//!
+//! We can see how we need to keep track of the `button::State` of each `Button` in our `Counter` state and provide a mutable reference to the widgets in our `view` logic. The widgets produced by `view` are __stateful__.
+//!
+//! While this approach forces users to keep track of widget state and causes impurity, I originally chose it because it allows `iced` to directly consume the widget tree produced by `view`. Since there is no internal state decoupled from `view` maintained by the runtime, `iced` does not need to compare (e.g. reconciliate) widget trees in order to ensure continuity.
+//!
+//! # Stateless widgets
+//! As the library matures, the need for some kind of persistent widget data (see #553) between `view` calls becomes more apparent (e.g. incremental rendering, animations, accessibility, etc.).
+//!
+//! If we are going to end up having persistent widget data anyways... There is no reason to have impure, stateful widgets anymore!
+//!
+//! With the help of this module, we can now write a pure `counter` example:
+//!
+//! ```ignore
+//! struct Counter {
+//! value: i32,
+//! }
+//!
+//! // ...
+//!
+//! impl Counter {
+//! fn view(&self) -> Column<Message> {
+//! Column::new()
+//! .push(Button::new("Increment").on_press(Message::IncrementPressed))
+//! .push(Text::new(self.value.to_string()).size(50))
+//! .push(Button::new("Decrement").on_press(Message::DecrementPressed))
+//! }
+//! }
+//! ```
+//!
+//! Notice how we no longer need to keep track of the `button::State`! The widgets in `iced_pure` do not take any mutable application state in `view`. They are __stateless__ widgets. As a consequence, we do not need mutable access to `self` in `view` anymore. `view` becomes __pure__.
+//!
+//! [The Elm Architecture]: https://guide.elm-lang.org/architecture/
+//!
//! [the original widgets]: crate::widget
//! [`button::State`]: crate::widget::button::State
//! [impure `Application`]: crate::Application
@@ -26,6 +104,7 @@ pub use application::Application;
pub use sandbox::Sandbox;
pub use iced_pure::helpers::*;
+pub use iced_pure::Widget;
pub use iced_pure::{Pure, State};
/// A generic, pure [`Widget`].
diff --git a/src/pure/widget.rs b/src/pure/widget.rs
index 6628b1fb..c84edde3 100644
--- a/src/pure/widget.rs
+++ b/src/pure/widget.rs
@@ -47,7 +47,7 @@ pub mod pane_grid {
//! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing,
//! drag and drop, and hotkey support.
//!
- //! [`pane_grid` example]: https://github.com/iced-rs/iced/tree/0.3/examples/pane_grid
+ //! [`pane_grid` example]: https://github.com/iced-rs/iced/tree/0.4/examples/pane_grid
pub use iced_pure::widget::pane_grid::{
Axis, Configuration, Direction, DragEvent, Line, Node, Pane,
ResizeEvent, Split, State, StyleSheet,
@@ -118,6 +118,15 @@ pub mod text_input {
iced_pure::widget::TextInput<'a, Message, Renderer>;
}
+pub mod tooltip {
+ //! Display a widget over another.
+ pub use iced_pure::widget::tooltip::Position;
+
+ /// A widget allowing the selection of a single value from a list of options.
+ pub type Tooltip<'a, Message> =
+ iced_pure::widget::Tooltip<'a, Message, crate::Renderer>;
+}
+
pub use iced_pure::widget::progress_bar;
pub use iced_pure::widget::rule;
pub use iced_pure::widget::slider;
@@ -135,6 +144,7 @@ pub use scrollable::Scrollable;
pub use slider::Slider;
pub use text_input::TextInput;
pub use toggler::Toggler;
+pub use tooltip::Tooltip;
#[cfg(feature = "canvas")]
pub use iced_graphics::widget::pure::canvas;