pub mod key;
mod painting_style;
use std::ops::DerefMut;
pub use key::{Key, KeyWidget};
pub use painting_style::*;
pub mod image_widget;
pub mod keep_alive;
pub use keep_alive::*;
mod theme;
use smallvec::SmallVec;
pub use theme::*;
mod cursor;
pub use cursor::*;
pub use winit::window::CursorIcon;
mod margin;
pub use margin::*;
mod foreground;
mod padding;
pub use foreground::*;
pub use padding::*;
mod scrollable;
pub use scrollable::*;
mod transform_widget;
pub use transform_widget::*;
mod visibility;
pub use visibility::*;
mod ignore_pointer;
pub use ignore_pointer::*;
mod void;
pub use void::Void;
mod unconstrained_box;
pub use unconstrained_box::*;
mod opacity;
pub use opacity::*;
mod anchor;
pub use anchor::*;
mod layout_box;
pub use layout_box::*;
pub mod align;
pub use align::*;
pub mod fitted_box;
pub use fitted_box::*;
pub mod svg;
pub use svg::*;
pub mod clip;
pub use clip::*;
pub mod clip_boundary;
pub use clip_boundary::*;
pub mod focus_node;
pub use focus_node::*;
pub mod focus_scope;
pub use focus_scope::*;
pub mod global_anchor;
pub use global_anchor::*;
mod mix_builtin;
pub use mix_builtin::*;
pub mod container;
pub use container::*;
mod class;
pub use class::*;
mod constrained_box;
pub use constrained_box::*;
mod text_style;
pub use text_style::*;
mod smooth_layout;
pub use smooth_layout::*;
mod track_widget_id;
pub use track_widget_id::*;
mod text;
pub use text::*;
mod tooltips;
pub use tooltips::*;
mod providers;
pub use providers::*;
mod border;
pub use border::*;
mod radius;
pub use radius::*;
mod background;
pub use background::*;
use crate::prelude::*;
#[derive(Default)]
pub struct FatObj<T> {
host: T,
track_id: Option<State<TrackWidgetId>>,
class: Option<State<Class>>,
padding: Option<State<Padding>>,
fitted_box: Option<State<FittedBox>>,
constrained_box: Option<State<ConstrainedBox>>,
radius: Option<State<RadiusWidget>>,
border: Option<State<BorderWidget>>,
background: Option<State<Background>>,
foreground: Option<State<Foreground>>,
scrollable: Option<State<ScrollableWidget>>,
layout_box: Option<State<LayoutBox>>,
mix_builtin: Option<MixBuiltin>,
request_focus: Option<State<RequestFocus>>,
cursor: Option<State<Cursor>>,
margin: Option<State<Margin>>,
transform: Option<State<TransformWidget>>,
opacity: Option<State<Opacity>>,
visibility: Option<State<Visibility>>,
h_align: Option<State<HAlignWidget>>,
v_align: Option<State<VAlignWidget>>,
relative_anchor: Option<State<RelativeAnchor>>,
global_anchor: Option<State<GlobalAnchor>>,
painting_style: Option<State<PaintingStyleWidget>>,
text_style: Option<State<TextStyleWidget>>,
keep_alive: Option<State<KeepAlive>>,
keep_alive_unsubscribe_handle: Option<Box<dyn Any>>,
tooltips: Option<State<Tooltips>>,
clip_boundary: Option<State<ClipBoundary>>,
providers: Option<SmallVec<[Provider; 1]>>,
}
#[macro_export]
macro_rules! fat_obj {
($($t: tt)*) => {
fn_widget! {
let obj = FatObj::<()>::default();
@ $obj { $($t)* }
}
};
}
impl<T> FatObj<T> {
pub fn new(host: T) -> Self { FatObj::<()>::default().with_child(host) }
pub fn map<V>(self, f: impl FnOnce(T) -> V) -> FatObj<V> {
FatObj {
host: f(self.host),
track_id: self.track_id,
class: self.class,
mix_builtin: self.mix_builtin,
request_focus: self.request_focus,
fitted_box: self.fitted_box,
border: self.border,
radius: self.radius,
background: self.background,
foreground: self.foreground,
padding: self.padding,
layout_box: self.layout_box,
cursor: self.cursor,
margin: self.margin,
scrollable: self.scrollable,
constrained_box: self.constrained_box,
transform: self.transform,
h_align: self.h_align,
v_align: self.v_align,
relative_anchor: self.relative_anchor,
global_anchor: self.global_anchor,
painting_style: self.painting_style,
text_style: self.text_style,
visibility: self.visibility,
opacity: self.opacity,
tooltips: self.tooltips,
clip_boundary: self.clip_boundary,
keep_alive: self.keep_alive,
keep_alive_unsubscribe_handle: self.keep_alive_unsubscribe_handle,
providers: self.providers,
}
}
pub fn is_empty(&self) -> bool {
self.track_id.is_none()
&& self.mix_builtin.is_none()
&& self.request_focus.is_none()
&& self.fitted_box.is_none()
&& self.border.is_none()
&& self.radius.is_none()
&& self.background.is_none()
&& self.foreground.is_none()
&& self.padding.is_none()
&& self.layout_box.is_none()
&& self.cursor.is_none()
&& self.margin.is_none()
&& self.scrollable.is_none()
&& self.constrained_box.is_none()
&& self.transform.is_none()
&& self.h_align.is_none()
&& self.v_align.is_none()
&& self.relative_anchor.is_none()
&& self.global_anchor.is_none()
&& self.class.is_none()
&& self.painting_style.is_none()
&& self.text_style.is_none()
&& self.visibility.is_none()
&& self.opacity.is_none()
&& self.keep_alive.is_none()
&& self.tooltips.is_none()
&& self.clip_boundary.is_none()
}
pub fn into_inner(self) -> T {
assert!(self.is_empty(), "Unwrap a FatObj with contains builtin widgets is not allowed.");
self.host
}
}
impl<T> FatObj<T> {
pub fn get_track_id_widget(&mut self) -> &State<TrackWidgetId> {
self
.track_id
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_class_widget(&mut self) -> &State<Class> {
self
.class
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_mix_builtin_widget(&mut self) -> &MixBuiltin {
self
.mix_builtin
.get_or_insert_with(MixBuiltin::default)
}
pub fn get_request_focus_widget(&mut self) -> &State<RequestFocus> {
self
.request_focus
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_mix_flags_widget(&mut self) -> &State<MixFlags> {
self.get_mix_builtin_widget().mix_flags()
}
pub fn trace_focus(&mut self) -> &mut Self {
self.get_mix_builtin_widget().trace_focus();
self
}
pub fn trace_hover(&mut self) -> &mut Self {
self.get_mix_builtin_widget().trace_hover();
self
}
pub fn trace_pointer_pressed(&mut self) -> &mut Self {
self
.get_mix_builtin_widget()
.trace_pointer_pressed();
self
}
pub fn get_fitted_box_widget(&mut self) -> &State<FittedBox> {
self
.fitted_box
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_border_widget(&mut self) -> &State<BorderWidget> {
self
.border
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_radius_widget(&mut self) -> &State<RadiusWidget> {
self
.radius
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_background_widget(&mut self) -> &State<Background> {
self
.background
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_foreground_widget(&mut self) -> &State<Foreground> {
self
.foreground
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_padding_widget(&mut self) -> &State<Padding> {
self
.padding
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_layout_box_widget(&mut self) -> &State<LayoutBox> {
self
.layout_box
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_cursor_widget(&mut self) -> &State<Cursor> {
self
.cursor
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_margin_widget(&mut self) -> &State<Margin> {
self
.margin
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_constrained_box_widget(&mut self) -> &State<ConstrainedBox> {
self
.constrained_box
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_scrollable_widget(&mut self) -> &State<ScrollableWidget> {
self
.scrollable
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_transform_widget(&mut self) -> &State<TransformWidget> {
self
.transform
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_h_align_widget(&mut self) -> &State<HAlignWidget> {
self
.h_align
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_v_align_widget(&mut self) -> &State<VAlignWidget> {
self
.v_align
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_relative_anchor_widget(&mut self) -> &State<RelativeAnchor> {
self
.relative_anchor
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_global_anchor_widget(&mut self) -> &State<GlobalAnchor> {
self
.global_anchor
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_painting_style_widget(&mut self) -> &State<PaintingStyleWidget> {
self
.painting_style
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_text_style_widget(&mut self) -> &State<TextStyleWidget> {
self.text_style.get_or_insert_with(|| {
State::value(TextStyleWidget {
text_style: Provider::of::<TextStyle>(BuildCtx::get())
.unwrap()
.clone(),
})
})
}
pub fn get_visibility_widget(&mut self) -> &State<Visibility> {
self
.visibility
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_opacity_widget(&mut self) -> &State<Opacity> {
self
.opacity
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_keep_alive_widget(&mut self) -> &State<KeepAlive> {
self
.keep_alive
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_tooltips_widget(&mut self) -> &State<Tooltips> {
self
.tooltips
.get_or_insert_with(|| State::value(<_>::default()))
}
pub fn get_clip_boundary_widget(&mut self) -> &State<ClipBoundary> {
self
.clip_boundary
.get_or_insert_with(|| State::value(<_>::default()))
}
}
macro_rules! on_mixin {
($this:ident, $on_method:ident, $f:ident) => {{
$this.get_mix_builtin_widget().$on_method($f);
$this
}};
}
impl<T> FatObj<T> {
pub fn on_event(mut self, f: impl FnMut(&mut Event) + 'static) -> Self {
on_mixin!(self, on_event, f)
}
pub fn on_mounted(mut self, f: impl FnOnce(&mut LifecycleEvent) + 'static) -> Self {
on_mixin!(self, on_mounted, f)
}
pub fn on_performed_layout(mut self, f: impl FnMut(&mut LifecycleEvent) + 'static) -> Self {
on_mixin!(self, on_performed_layout, f)
}
pub fn on_disposed(mut self, f: impl FnOnce(&mut LifecycleEvent) + 'static) -> Self {
on_mixin!(self, on_disposed, f)
}
pub fn on_pointer_down(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_down, f)
}
pub fn on_pointer_down_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_down_capture, f)
}
pub fn on_pointer_up(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_up, f)
}
pub fn on_pointer_up_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_up_capture, f)
}
pub fn on_pointer_move(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_move, f)
}
pub fn on_pointer_move_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_move_capture, f)
}
pub fn on_pointer_cancel(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_cancel, f)
}
pub fn on_pointer_enter(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_enter, f)
}
pub fn on_pointer_leave(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_pointer_leave, f)
}
pub fn on_tap(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_tap, f)
}
pub fn on_tap_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_tap_capture, f)
}
pub fn on_double_tap(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_double_tap, f)
}
pub fn on_double_tap_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_double_tap_capture, f)
}
pub fn on_triple_tap(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_triple_tap, f)
}
pub fn on_triple_tap_capture(mut self, f: impl FnMut(&mut PointerEvent) + 'static) -> Self {
on_mixin!(self, on_triple_tap_capture, f)
}
pub fn on_x_times_tap(
mut self, (times, f): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self
.get_mix_builtin_widget()
.on_x_times_tap((times, f));
self
}
pub fn on_x_times_tap_capture(
mut self, (times, f): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self
.get_mix_builtin_widget()
.on_x_times_tap_capture((times, f));
self
}
pub fn on_wheel(mut self, f: impl FnMut(&mut WheelEvent) + 'static) -> Self {
on_mixin!(self, on_wheel, f)
}
pub fn on_wheel_capture(mut self, f: impl FnMut(&mut WheelEvent) + 'static) -> Self {
on_mixin!(self, on_wheel_capture, f)
}
pub fn on_ime_pre_edit(mut self, f: impl FnMut(&mut ImePreEditEvent) + 'static) -> Self {
on_mixin!(self, on_ime_pre_edit, f)
}
pub fn on_ime_pre_edit_capture(mut self, f: impl FnMut(&mut ImePreEditEvent) + 'static) -> Self {
on_mixin!(self, on_ime_pre_edit_capture, f)
}
pub fn on_chars(mut self, f: impl FnMut(&mut CharsEvent) + 'static) -> Self {
on_mixin!(self, on_chars, f)
}
pub fn on_chars_capture(mut self, f: impl FnMut(&mut CharsEvent) + 'static) -> Self {
on_mixin!(self, on_chars_capture, f)
}
pub fn on_key_down(mut self, f: impl FnMut(&mut KeyboardEvent) + 'static) -> Self {
on_mixin!(self, on_key_down, f)
}
pub fn on_key_down_capture(mut self, f: impl FnMut(&mut KeyboardEvent) + 'static) -> Self {
on_mixin!(self, on_key_down_capture, f)
}
pub fn on_key_up(mut self, f: impl FnMut(&mut KeyboardEvent) + 'static) -> Self {
on_mixin!(self, on_key_up, f)
}
pub fn on_key_up_capture(mut self, f: impl FnMut(&mut KeyboardEvent) + 'static) -> Self {
on_mixin!(self, on_key_up_capture, f)
}
pub fn on_focus(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_focus, f)
}
pub fn on_blur(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_blur, f)
}
pub fn on_focus_in(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_focus_in, f)
}
pub fn on_focus_in_capture(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_focus_in_capture, f)
}
pub fn on_focus_out(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_focus_out, f)
}
pub fn on_custom_concrete_event<E: 'static>(
mut self, f: impl FnMut(&mut CustomEvent<E>) + 'static,
) -> Self {
on_mixin!(self, on_custom_concrete_event, f)
}
pub fn on_custom_event(mut self, f: impl FnMut(&mut RawCustomEvent) + 'static) -> Self {
on_mixin!(self, on_custom_event, f)
}
pub fn on_focus_out_capture(mut self, f: impl FnMut(&mut FocusEvent) + 'static) -> Self {
on_mixin!(self, on_focus_out_capture, f)
}
pub fn tab_index<const M: usize>(self, tab_idx: impl DeclareInto<i16, M>) -> Self {
self.declare_builtin_init(
tab_idx,
|this| this.get_mix_builtin_widget().mix_flags(),
|m, v| m.set_tab_index(v),
)
}
pub fn class<const M: usize>(self, cls: impl DeclareInto<ClassName, M>) -> Self {
self.declare_builtin_init(cls, Self::get_class_widget, |c, cls| c.class = Some(cls))
}
pub fn auto_focus<const M: usize>(self, v: impl DeclareInto<bool, M>) -> Self {
self.declare_builtin_init(
v,
|this| this.get_mix_builtin_widget().mix_flags(),
|m, v| m.set_auto_focus(v),
)
}
pub fn box_fit<const M: usize>(self, v: impl DeclareInto<BoxFit, M>) -> Self {
self.declare_builtin_init(v, Self::get_fitted_box_widget, |m, v| m.box_fit = v)
}
pub fn painting_style<const M: usize>(self, v: impl DeclareInto<PaintingStyle, M>) -> Self {
self.declare_builtin_init(v, Self::get_painting_style_widget, |m, v| m.painting_style = v)
}
pub fn text_style<const M: usize>(self, v: impl DeclareInto<TextStyle, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style = v)
}
pub fn font_size<const M: usize>(self, v: impl DeclareInto<f32, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style.font_size = v)
}
pub fn font_face<const M: usize>(self, v: impl DeclareInto<FontFace, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style.font_face = v)
}
pub fn letter_spacing<const M: usize>(self, v: impl DeclareInto<f32, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style.letter_space = v)
}
pub fn text_line_height<const M: usize>(self, v: impl DeclareInto<f32, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style.line_height = v)
}
pub fn text_overflow<const M: usize>(self, v: impl DeclareInto<TextOverflow, M>) -> Self {
self.declare_builtin_init(v, Self::get_text_style_widget, |m, v| m.text_style.overflow = v)
}
pub fn background<const M: usize>(self, v: impl DeclareInto<Brush, M>) -> Self {
self.declare_builtin_init(v, Self::get_background_widget, |m, v| m.background = v)
}
pub fn foreground<const M: usize>(self, v: impl DeclareInto<Brush, M>) -> Self {
self.declare_builtin_init(v, Self::get_foreground_widget, |m, v| m.foreground = v)
}
pub fn border<const M: usize>(self, v: impl DeclareInto<Border, M>) -> Self {
self.declare_builtin_init(v, Self::get_border_widget, |m, v| m.border = v)
}
pub fn radius<const M: usize>(self, v: impl DeclareInto<Radius, M>) -> Self {
self.declare_builtin_init(v, Self::get_radius_widget, |m, v| m.radius = v)
}
pub fn padding<const M: usize>(self, v: impl DeclareInto<EdgeInsets, M>) -> Self {
self.declare_builtin_init(v, Self::get_padding_widget, |m, v| m.padding = v)
}
pub fn cursor<const M: usize>(self, v: impl DeclareInto<CursorIcon, M>) -> Self {
self.declare_builtin_init(v, Self::get_cursor_widget, |m, v| m.cursor = v)
}
pub fn margin<const M: usize>(self, v: impl DeclareInto<EdgeInsets, M>) -> Self {
self.declare_builtin_init(v, Self::get_margin_widget, |m, v| m.margin = v)
}
pub fn clamp<const M: usize>(self, v: impl DeclareInto<BoxClamp, M>) -> Self {
self.declare_builtin_init(v, Self::get_constrained_box_widget, |m, v| m.clamp = v)
}
pub fn scrollable<const M: usize>(self, v: impl DeclareInto<Scrollable, M>) -> Self {
self.declare_builtin_init(v, Self::get_scrollable_widget, |m, v| m.scrollable = v)
}
pub fn transform<const M: usize>(self, v: impl DeclareInto<Transform, M>) -> Self {
self.declare_builtin_init(v, Self::get_transform_widget, |m, v| m.transform = v)
}
pub fn h_align<const M: usize>(self, v: impl DeclareInto<HAlign, M>) -> Self {
self.declare_builtin_init(v, Self::get_h_align_widget, |m, v| m.h_align = v)
}
pub fn v_align<const M: usize>(self, v: impl DeclareInto<VAlign, M>) -> Self {
self.declare_builtin_init(v, Self::get_v_align_widget, |m, v| m.v_align = v)
}
pub fn anchor<const M: usize>(self, v: impl DeclareInto<Anchor, M>) -> Self {
self.declare_builtin_init(v, Self::get_relative_anchor_widget, |m, v| m.anchor = v)
}
pub fn global_anchor_x<const M: usize>(self, v: impl DeclareInto<GlobalAnchorX, M>) -> Self {
self.declare_builtin_init(v, Self::get_global_anchor_widget, |m, v| m.global_anchor_x = v)
}
pub fn global_anchor_y<const M: usize>(self, v: impl DeclareInto<GlobalAnchorY, M>) -> Self {
self.declare_builtin_init(v, Self::get_global_anchor_widget, |m, v| m.global_anchor_y = v)
}
pub fn visible<const M: usize>(self, v: impl DeclareInto<bool, M>) -> Self {
self.declare_builtin_init(v, Self::get_visibility_widget, |m, v| m.visible = v)
}
pub fn opacity<const M: usize>(self, v: impl DeclareInto<f32, M>) -> Self {
self.declare_builtin_init(v, Self::get_opacity_widget, |m, v| m.opacity = v)
}
pub fn tooltips<const M: usize>(self, v: impl DeclareInto<CowArc<str>, M>) -> Self {
self.declare_builtin_init(v, Self::get_tooltips_widget, |m, v| m.tooltips = v)
}
pub fn clip_boundary<const M: usize>(self, v: impl DeclareInto<bool, M>) -> Self {
self.declare_builtin_init(v, Self::get_clip_boundary_widget, |m, v| m.clip_boundary = v)
}
pub fn keep_alive<const M: usize>(mut self, v: impl DeclareInto<bool, M>) -> Self {
let (v, o) = v.declare_into().unzip();
let d = self.get_keep_alive_widget();
d.write().keep_alive = v;
if let Some(o) = o {
let c_delay = d.clone_writer();
let u = o
.subscribe(move |(_, v)| {
c_delay.write().keep_alive = v;
})
.unsubscribe_when_dropped();
self.keep_alive_unsubscribe_handle = Some(Box::new(u));
}
self
}
pub fn track_id(mut self) -> Self {
self.get_track_id_widget();
self
}
pub fn providers(mut self, providers: impl Into<SmallVec<[Provider; 1]>>) -> Self {
if let Some(vec) = self.providers.as_mut() {
vec.extend(providers.into());
} else {
self.providers = Some(providers.into());
}
self
}
fn declare_builtin_init<V: 'static, B: 'static, const M: usize>(
mut self, init: impl DeclareInto<V, M>, get_builtin: impl FnOnce(&mut Self) -> &State<B>,
set_value: fn(&mut B, V),
) -> Self {
let builtin = get_builtin(&mut self);
let (v, o) = init.declare_into().unzip();
set_value(&mut *builtin.silent(), v);
if let Some(o) = o {
let c_builtin = builtin.clone_writer();
let u = o.subscribe(move |(_, v)| set_value(&mut *c_builtin.write(), v));
self.on_disposed(move |_| u.unsubscribe())
} else {
self
}
}
}
impl<T> FatObj<T> {
pub fn take_scrollable_widget(&mut self) -> Option<State<ScrollableWidget>> {
self.scrollable.take()
}
pub fn has_class(&self) -> bool { self.class.is_some() }
}
pub trait FatDeclarerExtend: Sized {
type Target;
fn finish(this: FatObj<Self>) -> FatObj<Self::Target>;
}
impl<T: FatDeclarerExtend> ObjDeclarer for FatObj<T> {
type Target = FatObj<T::Target>;
fn finish(self) -> Self::Target { T::finish(self) }
}
impl FatDeclarerExtend for () {
type Target = ();
fn finish(this: FatObj<()>) -> FatObj<()> { this }
}
impl<'w, T, const M: usize> IntoWidgetStrict<'w, M> for FatObj<T>
where
T: IntoWidget<'w, M>,
{
fn into_widget_strict(self) -> Widget<'w> { self.map(|w| w.into_widget()).compose() }
}
impl<'a> FatObj<Widget<'a>> {
fn compose(mut self) -> Widget<'a> {
macro_rules! compose_builtin_widgets {
($host: ident + [$($field: ident),*]) => {
$(
if let Some($field) = self.$field {
$host = $field.with_child($host).into_widget();
}
)*
};
}
macro_rules! consume_providers_widget {
($host: ident, + [$($field: ident: $w_ty: ty),*]) => {
$(
if let Some($field) = self.$field {
self
.providers
.get_or_insert_default()
.push(<$w_ty>::into_provider($field));
}
)*
};
}
let mut host = self.host;
consume_providers_widget!(host, + [
painting_style: PaintingStyleWidget,
text_style: TextStyleWidget
]);
compose_builtin_widgets!(
host
+ [
track_id,
padding,
fitted_box,
foreground,
border,
background,
clip_boundary,
radius,
scrollable,
layout_box
]
);
if let Some(providers) = self.providers {
host = Providers::new(providers).with_child(host);
}
compose_builtin_widgets!(
host
+ [
class,
constrained_box,
tooltips,
margin,
cursor,
mix_builtin,
request_focus,
transform,
opacity,
visibility,
h_align,
v_align,
relative_anchor,
global_anchor,
keep_alive
]
);
if let Some(h) = self.keep_alive_unsubscribe_handle {
host = host.attach_anonymous_data(h);
}
host
}
}
impl FatObj<()> {
#[inline]
pub fn with_child<C>(self, child: C) -> FatObj<C> { self.map(move |_| child) }
}
impl<T> std::ops::Deref for FatObj<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target { &self.host }
}
impl<T> std::ops::DerefMut for FatObj<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.host }
}
pub struct DeclarerWithSubscription<T> {
inner: T,
subscribes: SmallVec<[BoxSubscription<'static>; 1]>,
}
impl<T> DeclarerWithSubscription<T> {
pub fn new(host: T, subscribes: SmallVec<[BoxSubscription<'static>; 1]>) -> Self {
Self { inner: host, subscribes }
}
}
impl<T> Deref for DeclarerWithSubscription<T> {
type Target = T;
fn deref(&self) -> &Self::Target { &self.inner }
}
impl<T> DerefMut for DeclarerWithSubscription<T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }
}
impl<T> DeclarerWithSubscription<T> {
fn map<M>(self, f: impl FnOnce(T) -> M) -> DeclarerWithSubscription<M> {
DeclarerWithSubscription { inner: f(self.inner), subscribes: self.subscribes }
}
}
impl<'w, T, const M: usize> IntoWidgetStrict<'w, M> for DeclarerWithSubscription<T>
where
T: IntoWidget<'w, M>,
{
fn into_widget_strict(self) -> Widget<'w> {
let DeclarerWithSubscription { inner: host, subscribes } = self;
let w = host.into_widget();
if subscribes.is_empty() {
w
} else {
fn_widget! {
let w = FatObj::new(w);
@ $w {
on_disposed: move |_| {
subscribes.into_iter().for_each(|u| u.unsubscribe());
}
}
}
.into_widget()
}
}
}
impl<T: SingleChild> SingleChild for DeclarerWithSubscription<T> {
fn with_child<'c, const M: usize>(self, child: impl IntoChildSingle<'c, M>) -> Widget<'c> {
self.map(|w| w.with_child(child)).into_widget()
}
fn into_parent(self: Box<Self>) -> Widget<'static> { (*self).into_widget() }
}
impl<T: MultiChild> MultiChild for DeclarerWithSubscription<T> {
type Target<'c> = MultiPair<'c>;
fn with_child<'c, const N: usize, const M: usize>(
self, child: impl IntoChildMulti<'c, N, M>,
) -> MultiPair<'c> {
MultiPair::new(self, child)
}
fn into_parent(self: Box<Self>) -> Widget<'static> { (*self).into_widget() }
}
impl<'w, T, C, const TML: bool, const WRITER: bool, const N: usize, const M: usize>
ComposeWithChild<'w, C, WRITER, TML, N, M> for DeclarerWithSubscription<T>
where
T: ComposeWithChild<'w, C, WRITER, TML, N, M>,
{
type Target = DeclarerWithSubscription<T::Target>;
fn with_child(self, child: C) -> Self::Target { self.map(|host| host.with_child(child)) }
}
impl Declare for FatObj<()> {
type Builder = Self;
fn declarer() -> Self::Builder { FatObj::default() }
}