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
use std::fmt::Debug;
use super::Space;
use crate::styles::{ComponentDefinition, ContextFreeComponent};
use crate::value::{Destination, Dynamic};
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
/// A widget that provides access to a [`ComponentDefinition`]'s value through a
/// [`Dynamic`].
///
/// This widget enables access to runtime values provided by the theme without
/// creating a custom widget. After creating a probe, [`value()`](Self::value)
/// can be used to observe and use the value.
///
/// The theme information retrieved will be the effective theme at the location
/// the probe is inserted in the widget hierarchy.
#[derive(Debug)]
pub struct ComponentProbe<Component>
where
Component: ComponentDefinition,
{
component: Component,
probed: Dynamic<Component::ComponentType>,
child: WidgetRef,
}
impl<Component> ComponentProbe<Component>
where
Component: ComponentDefinition,
{
/// Returns a new probe that provides access to the runtime value of
/// `Component`.
///
/// The initial contents of the dynamic will be `initial_value`.
pub fn new(component: Component, initial_value: Component::ComponentType) -> Self {
Self::new_wrapping(component, initial_value, Space::clear())
}
/// Returns a new probe wrapping `child` that provides access to the runtime
/// value of this component.
///
/// The initial contents of the dynamic will be `initial_value`.
pub fn new_wrapping(
component: Component,
initial_value: Component::ComponentType,
child: impl MakeWidget,
) -> Self {
Self {
component,
probed: Dynamic::new(initial_value),
child: WidgetRef::new(child),
}
}
/// Returns a new probe that provides access to the runtime value of
/// `Component`.
pub fn default_for(component: Component) -> Self
where
Component: ContextFreeComponent,
{
let default = component.default();
Self::new(component, default)
}
/// Returns a new probe wrapping `child` that provides access to the runtime
/// value of this component.
pub fn default_wrapping(component: Component, child: impl MakeWidget) -> Self
where
Component: ContextFreeComponent,
{
let default = component.default();
Self::new_wrapping(component, default, child)
}
/// Returns the dynamic that contains the component's current value.
///
/// This dynamic's contents will be updated whenever this probe is
/// invalidated.
pub const fn value(&self) -> &Dynamic<Component::ComponentType> {
&self.probed
}
}
impl<Component> WrapperWidget for ComponentProbe<Component>
where
Component: ComponentDefinition + Debug + Send + 'static,
Component::ComponentType: PartialEq + Debug + Send + 'static,
{
fn child_mut(&mut self) -> &mut crate::widget::WidgetRef {
&mut self.child
}
fn redraw_foreground(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) {
self.probed.set(context.get(&self.component));
}
}