Source<T> + Destination<T> (breaking)

Refs #98

This refactor overhauls the reactive system to move all the reactive
methods to traits. The side effect of this change is that now
DynamicReader's API is the same as Dynamic's API, but because it only
implements Source<T>, DynamicReader does not offer any mutation
functions.

While it's unfortunate to have more traits to include to use Cushy, this
seems like the best option, and it offers a path to try to integrate
this into the tuple ForEach/MapEach traits. Unfortunately, my attempt at
doing those in this set of changes led to issues specifying generic
associated lifetimes for the DynamicGuard. But, I was also in the middle
of this larger refactoring, so it might be that a fresh attempt will
succeed.
This commit is contained in:
Jonathan Johnson 2024-01-02 09:00:29 -08:00
parent c1d6e3f7fd
commit e70e92726c
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
50 changed files with 829 additions and 611 deletions

View file

@ -14,6 +14,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
properly when used in a `WidgetInstance` shared between multiple windows.
- `WidgetRef::unmount_in` should be called when the widget is being unmounted to
clean up individual window state.
- `Dynamic<T>` and `DynamicReader<T>` have had most of their functions moved
into the traits `Source<T>` and `Destination<T>`. This unifies the APIs
between the two types, and offers a path for other specialized reactive data
types to all share a unified API.
- `map_mut` now takes a `Mutable<'_, T>` parameter instead of an `&mut T`
parameter. This type tracks whether the reference is accessed using
`DerefMut`, allowing `map_mut` to skip invoking change callbacks if only
`Deref` is used.
### Fixed
@ -73,6 +81,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `RunningWindow::kludgine_id()` returns a unique id for that window.
- `WindowLocal<T>` is a `HashMap`-based type that stores data on a per-window
basis using `RunningWindow::kludgine_id()` as the key.
- `Source<T>` and `Destination<T>` are new traits that contain the reactive data
model's API interface. `Dynamic<T>` implements both traits, and
`DynamicReader<T>` implements only `Source<T>`.
[99]: https://github.com/khonsulabs/cushy/issues/99
[120]: https://github.com/khonsulabs/cushy/issues/120

View file

@ -1,7 +1,7 @@
use std::time::Duration;
use cushy::animation::{AnimationHandle, AnimationTarget, IntoAnimate, Spawn};
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic};
use cushy::widget::MakeWidget;
use cushy::widgets::progress::Progressable;
use cushy::{Run, WithClone};

View file

@ -4,7 +4,7 @@
use std::time::Duration;
use cushy::animation::ZeroToOne;
use cushy::value::{Dynamic, Switchable};
use cushy::value::{Destination, Dynamic, Switchable};
use cushy::widget::MakeWidget;
use cushy::widgets::progress::{Progress, Progressable};
use cushy::Run;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::Run;

View file

@ -16,7 +16,7 @@
//! ┃ ┃ ┣ clicked_button Label
//! ```
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic};
use cushy::widget::MakeWidget;
use cushy::widgets::button::{ButtonHoverBackground, ButtonHoverForeground};
use cushy::Run;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::button::ButtonKind;
use cushy::Run;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::checkbox::{Checkable, CheckboxState};
use cushy::Run;

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use cushy::value::{Dynamic, MapEach};
use cushy::value::{Dynamic, MapEach, Source};
use cushy::widget::{Children, MakeWidget};
use cushy::widgets::input::InputValue;
use cushy::Run;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic};
use cushy::widget::{MakeWidget, WidgetInstance};
use cushy::widgets::container::ContainerShadow;
use cushy::window::ThemeMode;
@ -22,7 +22,7 @@ fn set_of_containers(repeat: usize, theme_mode: Dynamic<ThemeMode>) -> WidgetIns
"Toggle Theme Mode"
.into_button()
.on_click(move |_| {
theme_mode.map_mut(|mode| mode.toggle());
theme_mode.map_mut(|mut mode| mode.toggle());
})
.make_widget()
};

View file

@ -1,6 +1,6 @@
use std::string::ToString;
use cushy::value::Dynamic;
use cushy::value::{Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::Run;
use figures::units::Lp;

View file

@ -1,7 +1,7 @@
//! This example shows two approaches to writing custom widgets: implementing
//! traits or using the [`Custom`] widget with callbacks.
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance, WidgetTag, HANDLED};
use cushy::widgets::Custom;
use cushy::Run;

View file

@ -1,5 +1,5 @@
use cushy::debug::DebugContext;
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::slider::Slidable;
use cushy::{Application, Open, PendingApp};
@ -46,7 +46,7 @@ fn open_a_window(
app: &dyn Application,
) {
*window_count.lock() += 1;
let window_number = total_windows.map_mut(|total| {
let window_number = total_windows.map_mut(|mut total| {
*total += 1;
*total
});

View file

@ -1,6 +1,6 @@
use std::process::exit;
use cushy::value::{Dynamic, MapEach};
use cushy::value::{Dynamic, MapEach, Source};
use cushy::widget::{MakeWidget, MakeWidgetWithTag, WidgetTag};
use cushy::widgets::grid::{Grid, GridDimension, GridWidgets};
use cushy::widgets::input::{InputValue, MaskedString};

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::input::InputValue;
use cushy::widgets::slider::Slidable;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic};
use cushy::widget::{MakeWidget, HANDLED, IGNORED};
use cushy::widgets::input::InputValue;
use cushy::Run;
@ -20,8 +20,8 @@ fn main() -> cushy::Result {
.and(chat_message.clone().into_input().on_key(move |input| {
match (input.state, input.logical_key) {
(ElementState::Pressed, Key::Named(NamedKey::Enter)) => {
let new_message = chat_message.map_mut(std::mem::take);
chat_log.map_mut(|chat_log| {
let new_message = chat_message.take();
chat_log.map_mut(|mut chat_log| {
chat_log.push_str(&new_message);
chat_log.push('\n');
});

View file

@ -1,5 +1,5 @@
use cushy::animation::ZeroToOne;
use cushy::value::{Dynamic, MapEachCloned};
use cushy::value::{Dynamic, MapEachCloned, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::image::{Aspect, ImageScaling};
use cushy::widgets::slider::Slidable;

View file

@ -1,6 +1,6 @@
use std::process::exit;
use cushy::value::{Dynamic, Validations};
use cushy::value::{Dynamic, Source, Validations};
use cushy::widget::MakeWidget;
use cushy::widgets::input::{InputValue, MaskedString};
use cushy::widgets::layers::OverlayLayer;

View file

@ -1,5 +1,5 @@
use cushy::kludgine::include_texture;
use cushy::value::{Dynamic, MapEach};
use cushy::value::{Destination, Dynamic, MapEach};
use cushy::widget::MakeWidget;
use cushy::widgets::Image;
use cushy::window::PendingWindow;
@ -63,13 +63,13 @@ fn open_another_window(
counter: &Dynamic<usize>,
texture: &LazyTexture,
) {
let my_number = counter.map_mut(|count| {
let my_number = counter.map_mut(|mut count| {
*count += 1;
*count
});
let open_windows = open_windows.clone();
open_windows.map_mut(|open_windows| *open_windows += 1);
open_windows.map_mut(|mut open_windows| *open_windows += 1);
let window = PendingWindow::default();
let handle = window.handle();
@ -87,7 +87,7 @@ fn open_another_window(
.into_rows()
.centered(),
)
.on_close(move || open_windows.map_mut(|open_windows| *open_windows -= 1))
.on_close(move || open_windows.map_mut(|mut open_windows| *open_windows -= 1))
.open(app)
.expect("error opening another window");
}

View file

@ -1,5 +1,5 @@
use cushy::animation::{LinearInterpolate, PercentBetween};
use cushy::value::{Dynamic, ForEach};
use cushy::value::{Destination, Dynamic, ForEach, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::checkbox::Checkable;
use cushy::widgets::input::InputValue;

View file

@ -1,4 +1,4 @@
use cushy::value::{Dynamic, Switchable};
use cushy::value::{Destination, Dynamic, Switchable};
use cushy::widget::{MakeWidget, WidgetInstance};
use cushy::Run;

View file

@ -5,7 +5,7 @@ use cushy::styles::{
ColorScheme, ColorSchemeBuilder, ColorSource, ColorTheme, FixedTheme, SurfaceTheme, Theme,
ThemePair,
};
use cushy::value::{Dynamic, MapEachCloned};
use cushy::value::{Destination, Dynamic, MapEachCloned, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::checkbox::Checkable;
use cushy::widgets::color::ColorSourcePicker;
@ -218,9 +218,10 @@ fn color_editor(color: &Dynamic<ColorSource>) -> impl MakeWidget {
hue.for_each_cloned({
let color = color.clone();
move |hue| {
let mut source = color.get();
source.hue = OklabHue::new(hue);
color.set(source);
if let Ok(mut source) = color.try_get() {
source.hue = OklabHue::new(hue);
color.set(source);
}
}
})
.persist();
@ -231,9 +232,10 @@ fn color_editor(color: &Dynamic<ColorSource>) -> impl MakeWidget {
.for_each_cloned({
let color = color.clone();
move |saturation| {
let mut source = color.get();
source.saturation = saturation;
color.set(source);
if let Ok(mut source) = color.try_get() {
source.saturation = saturation;
color.set(source);
}
}
})
.persist();

View file

@ -3,7 +3,7 @@ use std::iter;
use std::ops::Not;
use std::time::SystemTime;
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::button::ButtonKind;
use cushy::{Run, WithClone};

View file

@ -11,7 +11,7 @@ use cushy::kludgine::tilemap::{
DebugGrid, Object, ObjectLayer, TileArray, TileKind, TileMapFocus, TILE_SIZE,
};
use cushy::kludgine::Color;
use cushy::value::Dynamic;
use cushy::value::{Destination, Dynamic};
use cushy::widgets::TileMap;
use cushy::{Run, Tick};
use figures::FloatConversion;
@ -71,7 +71,7 @@ fn main() -> cushy::Result {
let cursor_pos = input.mouse.as_ref().map(|mouse| mouse.position);
layers.map_mut(|layers| {
layers.map_mut(|mut layers| {
let player = &mut layers.1[myself];
let animation_tag = match direction.x.total_cmp(&0.) {

View file

@ -1,4 +1,4 @@
use cushy::value::{Dynamic, Validations};
use cushy::value::{Destination, Dynamic, Validations};
use cushy::widget::MakeWidget;
use cushy::widgets::input::InputValue;
use cushy::Run;

View file

@ -1,4 +1,4 @@
use cushy::value::Dynamic;
use cushy::value::{Dynamic, Source};
use cushy::widget::{MakeWidget, WidgetInstance};
use cushy::Run;
use figures::Size;

View file

@ -57,7 +57,7 @@ use kludgine::Color;
use crate::animation::easings::Linear;
use crate::styles::{Component, RequireInvalidation};
use crate::utils::{run_in_bg, IgnorePoison};
use crate::value::Dynamic;
use crate::value::{Destination, Dynamic, Source};
static ANIMATIONS: Mutex<Animating> = Mutex::new(Animating::new());
static NEW_ANIMATIONS: Condvar = Condvar::new();

View file

@ -19,7 +19,7 @@ use crate::styles::components::{
};
use crate::styles::{ComponentDefinition, Styles, Theme, ThemePair};
use crate::tree::Tree;
use crate::value::{IntoValue, Value};
use crate::value::{IntoValue, Source, Value};
use crate::widget::{EventHandling, MountedWidget, RootBehavior, WidgetId, WidgetInstance};
use crate::window::{CursorState, RunningWindow, ThemeMode};
use crate::ConstraintLimit;

View file

@ -4,7 +4,7 @@ use std::fmt::Debug;
use alot::OrderedLots;
use crate::value::{Dynamic, DynamicReader, ForEach, WeakDynamic};
use crate::value::{Dynamic, DynamicReader, ForEach, Source, WeakDynamic};
use crate::widget::{Children, MakeWidget, WidgetInstance};
use crate::widgets::grid::{Grid, GridWidgets};
use crate::window::Window;

View file

@ -23,7 +23,7 @@ use crate::animation::{EasingFunction, ZeroToOne};
use crate::context::WidgetContext;
use crate::names::Name;
use crate::utils::Lazy;
use crate::value::{Dynamic, IntoValue, Value};
use crate::value::{Dynamic, IntoValue, Source, Value};
#[macro_use]
pub mod components;

View file

@ -11,7 +11,7 @@ use kludgine::app::winit::keyboard::Key;
use crate::context::WidgetContext;
use crate::utils::IgnorePoison;
use crate::value::Dynamic;
use crate::value::{Destination, Dynamic};
use crate::widget::{EventHandling, HANDLED, IGNORED};
/// A fixed-rate callback that provides access to tracked input on its
@ -211,7 +211,7 @@ where
// Signal that we have a new frame, which will cause the widget to
// redraw.
data.tick_number.map_mut(|tick| *tick += 1);
data.tick_number.map_mut(|mut tick| *tick += 1);
// Wait for a frame to be rendered.
while state.keep_running {

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@ impl Align {
#[must_use]
pub fn align_left(mut self) -> Self {
self.edges
.map_mut(|edges| edges.left = FlexibleDimension::ZERO);
.map_mut(|mut edges| edges.left = FlexibleDimension::ZERO);
self
}
@ -44,7 +44,7 @@ impl Align {
#[must_use]
pub fn align_top(mut self) -> Self {
self.edges
.map_mut(|edges| edges.top = FlexibleDimension::ZERO);
.map_mut(|mut edges| edges.top = FlexibleDimension::ZERO);
self
}
@ -52,7 +52,7 @@ impl Align {
#[must_use]
pub fn align_bottom(mut self) -> Self {
self.edges
.map_mut(|edges| edges.bottom = FlexibleDimension::ZERO);
.map_mut(|mut edges| edges.bottom = FlexibleDimension::ZERO);
self
}
@ -60,14 +60,14 @@ impl Align {
#[must_use]
pub fn align_right(mut self) -> Self {
self.edges
.map_mut(|edges| edges.right = FlexibleDimension::ZERO);
.map_mut(|mut edges| edges.right = FlexibleDimension::ZERO);
self
}
/// Sets the left and right edges of alignment to 0 and returns self.
#[must_use]
pub fn fit_horizontally(mut self) -> Self {
self.edges.map_mut(|edges| {
self.edges.map_mut(|mut edges| {
edges.left = FlexibleDimension::ZERO;
edges.right = FlexibleDimension::ZERO;
});
@ -77,7 +77,7 @@ impl Align {
/// Sets the top and bottom edges of alignment to 0 and returns self.
#[must_use]
pub fn fit_vertically(mut self) -> Self {
self.edges.map_mut(|edges| {
self.edges.map_mut(|mut edges| {
edges.top = FlexibleDimension::ZERO;
edges.bottom = FlexibleDimension::ZERO;
});

View file

@ -19,7 +19,7 @@ use crate::styles::components::{
HighlightColor, IntrinsicPadding, OpaqueWidgetColor, OutlineColor, SurfaceColor, TextColor,
};
use crate::styles::{ColorExt, Styles};
use crate::value::{Dynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, IntoValue, Source, Value};
use crate::widget::{Callback, EventHandling, MakeWidget, Widget, WidgetRef, HANDLED};
use crate::window::WindowLocal;
use crate::FitMeasuredSize;

View file

@ -10,7 +10,7 @@ use kludgine::shapes::{PathBuilder, Shape, StrokeOptions};
use crate::context::{GraphicsContext, LayoutContext};
use crate::styles::components::{LineHeight, OutlineColor, TextColor, WidgetAccentColor};
use crate::styles::Dimension;
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Source, Value};
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
use crate::widgets::button::ButtonKind;
use crate::ConstraintLimit;

View file

@ -6,7 +6,7 @@ use figures::Size;
use crate::animation::easings::{EaseInQuadradic, EaseOutQuadradic};
use crate::animation::{AnimationHandle, AnimationTarget, EasingFunction, Spawn};
use crate::context::LayoutContext;
use crate::value::{Dynamic, IntoDynamic};
use crate::value::{Dynamic, IntoDynamic, Source};
use crate::widget::{MakeWidget, WidgetRef, WrappedLayout, WrapperWidget};
use crate::ConstraintLimit;

View file

@ -12,7 +12,7 @@ use crate::animation::ZeroToOne;
use crate::context::{EventContext, GraphicsContext};
use crate::styles::components::{HighlightColor, OutlineColor, TextColor};
use crate::styles::{ColorExt, ColorSource};
use crate::value::{Dynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, IntoValue, Source, Value};
use crate::widget::{EventHandling, Widget, HANDLED};
/// A widget that selects a [`ColorSource`].

View file

@ -10,7 +10,7 @@ use kludgine::Color;
use crate::context::{EventContext, GraphicsContext, LayoutContext, WidgetContext};
use crate::styles::components::{CornerRadius, IntrinsicPadding, Opacity, SurfaceColor};
use crate::styles::{Component, ContainerLevel, Dimension, Edges, RequireInvalidation, Styles};
use crate::value::{Dynamic, IntoValue, Value};
use crate::value::{Dynamic, IntoValue, Source, Value};
use crate::widget::{MakeWidget, RootBehavior, Widget, WidgetInstance, WidgetRef};
use crate::ConstraintLimit;

View file

@ -13,7 +13,7 @@ use crate::animation::{AnimationHandle, AnimationTarget, Spawn};
use crate::context::{EventContext, LayoutContext};
use crate::styles::components::{HighlightColor, IntrinsicPadding, LineHeight, OutlineColor};
use crate::styles::Dimension;
use crate::value::{Dynamic, IntoDynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value};
use crate::widget::{
EventHandling, MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance, WidgetRef, WidgetTag,
HANDLED, IGNORED,

View file

@ -6,7 +6,7 @@ use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture
use crate::animation::ZeroToOne;
use crate::context::LayoutContext;
use crate::value::{IntoValue, Value};
use crate::value::{IntoValue, Source, Value};
use crate::widget::Widget;
use crate::ConstraintLimit;

View file

@ -25,7 +25,7 @@ use zeroize::Zeroizing;
use crate::context::{EventContext, GraphicsContext, LayoutContext};
use crate::styles::components::{HighlightColor, IntrinsicPadding, OutlineColor, TextColor};
use crate::utils::ModifiersExt;
use crate::value::{Dynamic, Generation, IntoDynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, Generation, IntoDynamic, IntoValue, Source, Value};
use crate::widget::{Callback, EventHandling, Widget, HANDLED, IGNORED};
use crate::{ConstraintLimit, Lazy};
@ -189,7 +189,7 @@ where
}
fn replace_range(&mut self, start: Cursor, end: Cursor, new_text: &str) {
self.value.map_mut(|value| {
self.value.map_mut(|mut value| {
let value = value.as_string_mut();
let start = start.offset.min(value.len().saturating_sub(1));
let end = end.offset.min(value.len());

View file

@ -14,7 +14,7 @@ use crate::animation::easings::EaseOutQuadradic;
use crate::animation::{AnimationHandle, AnimationTarget, IntoAnimate, Spawn, ZeroToOne};
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
use crate::utils::IgnorePoison;
use crate::value::{Dynamic, DynamicGuard, IntoValue, Value};
use crate::value::{Destination, Dynamic, DynamicGuard, IntoValue, Source, Value};
use crate::widget::{
Callback, Children, MakeWidget, MountedChildren, MountedWidget, Widget, WidgetId, WidgetRef,
WrapperWidget,
@ -593,7 +593,7 @@ impl OverlayBuilder<'_> {
#[must_use]
pub fn show(self) -> OverlayHandle {
self.fade_in();
self.overlay.state.map_mut(|state| {
self.overlay.state.map_mut(|mut state| {
state.new_overlays += 1;
OverlayHandle {
state: self.overlay.state.clone(),

View file

@ -12,7 +12,7 @@ use crate::animation::easings::{EaseInQuadradic, EaseOutQuadradic};
use crate::animation::{
AnimationHandle, AnimationTarget, IntoAnimate, PercentBetween, Spawn, ZeroToOne,
};
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Value};
use crate::value::{Destination, Dynamic, IntoDynamic, IntoValue, MapEach, Source, Value};
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
use crate::widgets::slider::{InactiveTrackColor, Slidable, TrackColor, TrackSize};
use crate::widgets::Data;

View file

@ -9,7 +9,7 @@ use kludgine::DrawableExt;
use crate::context::{GraphicsContext, LayoutContext};
use crate::styles::components::{LineHeight, OutlineColor, WidgetAccentColor};
use crate::styles::Dimension;
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, DynamicReader, IntoDynamic, IntoValue, Source, Value};
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
use crate::widgets::button::ButtonKind;
use crate::ConstraintLimit;

View file

@ -13,7 +13,7 @@ use crate::animation::{AnimationHandle, AnimationTarget, IntoAnimate, Spawn, Zer
use crate::context::{AsEventContext, EventContext, LayoutContext};
use crate::styles::components::{EasingIn, EasingOut, LineHeight};
use crate::styles::Dimension;
use crate::value::Dynamic;
use crate::value::{Destination, Dynamic, Source};
use crate::widget::{EventHandling, MakeWidget, Widget, WidgetRef, HANDLED, IGNORED};
use crate::ConstraintLimit;

View file

@ -5,7 +5,7 @@ use kludgine::Color;
use crate::styles::components::OutlineColor;
use crate::styles::{Component, DynamicComponent};
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Value};
use crate::value::{Destination, Dynamic, IntoDynamic, IntoValue, MapEach, Source, Value};
use crate::widget::{MakeWidget, MakeWidgetWithTag, WidgetInstance};
use crate::widgets::button::{ButtonBackground, ButtonHoverBackground, ButtonKind};

View file

@ -19,7 +19,7 @@ use crate::styles::components::{
WidgetAccentColor,
};
use crate::styles::{Dimension, HorizontalOrder, VerticalOrder, VisualOrder};
use crate::value::{Dynamic, IntoDynamic, IntoValue, Value};
use crate::value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value};
use crate::widget::{EventHandling, Widget, HANDLED, IGNORED};
use crate::ConstraintLimit;
@ -445,7 +445,7 @@ where
let mut max = self.maximum.get_tracking_redraw(context);
if max < min {
self.maximum.map_mut(|max| *max = min.clone());
self.maximum.map_mut(|mut max| *max = min.clone());
max = min.clone();
}
let mut value_clamped = false;
@ -472,7 +472,7 @@ where
if value_clamped {
self.value
.map_mut(|v| *v = T::from_parts(start_value.clone(), end_value.clone()));
.map_mut(|mut v| *v = T::from_parts(start_value.clone(), end_value.clone()));
}
let start_percent = start_value.percent_between(&min, &max);

View file

@ -11,7 +11,7 @@ use crate::styles::components::{
use crate::styles::{
ComponentDefinition, IntoComponentValue, IntoDynamicComponentValue, StoredComponent, Styles,
};
use crate::value::{IntoValue, Value};
use crate::value::{Destination, IntoValue, Mutable, Value};
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
/// A widget that applies a set of [`Styles`] to all contained widgets.
@ -31,9 +31,9 @@ impl Style {
}
}
fn map_styles_mut<R>(&mut self, map: impl FnOnce(&mut Styles) -> R) -> R {
fn map_styles_mut<R>(&mut self, map: impl FnOnce(Mutable<'_, Styles>) -> R) -> R {
match &mut self.styles {
Value::Constant(styles) => map(styles),
Value::Constant(styles) => map(Mutable::from(styles)),
Value::Dynamic(dynamic) => dynamic.map_mut(map),
}
}
@ -48,7 +48,7 @@ impl Style {
where
Value<C::ComponentType>: IntoComponentValue,
{
self.map_styles_mut(|styles| {
self.map_styles_mut(|mut styles| {
styles.insert(name, component.into_value());
});
self
@ -64,7 +64,7 @@ impl Style {
where
Value<C::ComponentType>: IntoComponentValue,
{
self.map_styles_mut(|styles| {
self.map_styles_mut(|mut styles| {
styles.insert_named(
name.name().into_owned(),
StoredComponent::local(component.into_value()),
@ -84,7 +84,7 @@ impl Style {
where
Value<C::ComponentType>: IntoComponentValue,
{
self.map_styles_mut(|styles| {
self.map_styles_mut(|mut styles| {
styles.insert_dynamic(name, dynamic);
});
self

View file

@ -3,7 +3,7 @@ use std::fmt::Debug;
use figures::Size;
use crate::context::LayoutContext;
use crate::value::{Dynamic, DynamicReader, IntoDynamic};
use crate::value::{Dynamic, DynamicReader, IntoDynamic, Source};
use crate::widget::{WidgetInstance, WidgetRef, WrapperWidget};
use crate::ConstraintLimit;
@ -37,7 +37,7 @@ impl Switcher {
/// `widget_factory` each time `value` changes.
#[must_use]
pub fn new(source: impl IntoDynamic<WidgetInstance>) -> Self {
let mut source = source.into_dynamic().into_reader();
let source = source.into_dynamic().into_reader();
let child = WidgetRef::new(source.get());
Self { source, child }
}

View file

@ -8,7 +8,9 @@ use crate::styles::components::{
ErrorColor, LineHeight, LineHeight2, OutlineColor, TextColor, TextSize, TextSize2,
};
use crate::styles::Dimension;
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Validation, Value};
use crate::value::{
Destination, Dynamic, IntoDynamic, IntoValue, MapEach, Source, Validation, Value,
};
use crate::widget::{MakeWidget, MakeWidgetWithTag, WidgetInstance, WidgetRef, WrapperWidget};
/// A widget that displays validation information around another widget.

View file

@ -37,7 +37,9 @@ use crate::graphics::{FontState, Graphics};
use crate::styles::{Edges, FontFamilyList, ThemePair};
use crate::tree::Tree;
use crate::utils::ModifiersExt;
use crate::value::{Dynamic, DynamicReader, Generation, IntoDynamic, IntoValue, Value};
use crate::value::{
Destination, Dynamic, DynamicReader, Generation, IntoDynamic, IntoValue, Source, Value,
};
use crate::widget::{
EventHandling, MakeWidget, MountedWidget, OnceCallback, RootBehavior, Widget, WidgetId,
WidgetInstance, HANDLED, IGNORED,