use zng_app::widget::info::access::WidgetAccessInfoBuilder;
use zng_ext_l10n::Lang;
use zng_wgt::prelude::*;
use std::num::NonZeroU32;
pub use zng_view_api::access::{
AccessCmdName, AccessRole, AutoComplete, CurrentKind, Invalid, LiveIndicator, Orientation, Popup, SortDirection,
};
#[property(CONTEXT)]
pub fn access_role(child: impl UiNode, role: impl IntoVar<AccessRole>) -> impl UiNode {
with_access_state(child, role, |b, v| b.set_role(*v))
}
#[property(CONTEXT)]
pub fn access_commands(child: impl UiNode, commands: impl IntoVar<Vec<AccessCmdName>>) -> impl UiNode {
with_access_state(child, commands, |b, v| {
for cmd in v {
b.push_command(*cmd);
}
})
}
#[property(WIDGET, default(true))]
pub fn accessible(child: impl UiNode, accessible: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, accessible, |b, v| {
if !*v {
b.flag_inaccessible();
}
})
}
#[property(CONTEXT)]
pub fn auto_complete(child: impl UiNode, auto_complete: impl IntoVar<AutoComplete>) -> impl UiNode {
with_access_state(child, auto_complete, |b, v| b.set_auto_complete(*v))
}
#[property(CONTEXT)]
pub fn checked(child: impl UiNode, checked: impl IntoVar<Option<bool>>) -> impl UiNode {
with_access_state(child, checked, |b, v| b.set_checked(*v))
}
#[property(CONTEXT)]
pub fn current(child: impl UiNode, kind: impl IntoVar<CurrentKind>) -> impl UiNode {
with_access_state(child, kind, |b, v| b.set_current(*v))
}
#[property(CONTEXT)]
pub fn error_message(child: impl UiNode, invalid_wgt: impl IntoVar<WidgetId>) -> impl UiNode {
with_access_state(child, invalid_wgt, |b, v| b.set_error_message(*v))
}
#[property(CONTEXT)]
pub fn active_descendant(child: impl UiNode, descendant: impl IntoVar<WidgetId>) -> impl UiNode {
with_access_state(child, descendant, |b, v| b.set_active_descendant(*v))
}
#[property(CONTEXT)]
pub fn expanded(child: impl UiNode, expanded: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, expanded, |b, v| b.set_expanded(*v))
}
#[property(CONTEXT)]
pub fn popup(child: impl UiNode, popup: impl IntoVar<Popup>) -> impl UiNode {
with_access_state(child, popup, |b, v| b.set_popup(*v))
}
#[property(CONTEXT)]
pub fn label(child: impl UiNode, label: impl IntoVar<Txt>) -> impl UiNode {
with_access_state(child, label, |b, v| b.set_label(v.clone()))
}
#[property(CONTEXT)]
pub fn labelled_by_child(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, enabled, |b, v| {
if *v {
b.flag_labelled_by_child();
}
})
}
#[property(CONTEXT)]
pub fn level(child: impl UiNode, hierarchical_level: impl IntoVar<NonZeroU32>) -> impl UiNode {
with_access_state(child, hierarchical_level, |b, v| b.set_level(*v))
}
#[property(CONTEXT)]
pub fn multi_selectable(child: impl UiNode, multi_selectable: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, multi_selectable, |b, v| {
if *v {
b.flag_multi_selectable()
}
})
}
#[property(CONTEXT)]
pub fn orientation(child: impl UiNode, orientation: impl IntoVar<Orientation>) -> impl UiNode {
with_access_state(child, orientation, |b, v| b.set_orientation(*v))
}
#[property(CONTEXT)]
pub fn placeholder(child: impl UiNode, placeholder: impl IntoVar<Txt>) -> impl UiNode {
with_access_state(child, placeholder, |b, v| b.set_placeholder(v.clone()))
}
#[property(CONTEXT)]
pub fn read_only(child: impl UiNode, read_only: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, read_only, |b, v| {
if *v {
b.flag_read_only()
}
})
}
#[property(CONTEXT)]
pub fn required(child: impl UiNode, required: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, required, |b, v| {
if *v {
b.flag_required()
}
})
}
#[property(CONTEXT)]
pub fn selected(child: impl UiNode, selected: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, selected, |b, v| {
if *v {
b.flag_selected()
}
})
}
#[property(CONTEXT)]
pub fn sort(child: impl UiNode, direction: impl IntoVar<SortDirection>) -> impl UiNode {
with_access_state(child, direction, |b, v| b.set_sort(*v))
}
#[property(CONTEXT)]
pub fn value_max(child: impl UiNode, max: impl IntoVar<f64>) -> impl UiNode {
with_access_state(child, max, |b, v| b.set_value_max(*v))
}
#[property(CONTEXT)]
pub fn value_min(child: impl UiNode, min: impl IntoVar<f64>) -> impl UiNode {
with_access_state(child, min, |b, v| b.set_value_min(*v))
}
#[property(CONTEXT)]
pub fn value(child: impl UiNode, value: impl IntoVar<f64>) -> impl UiNode {
with_access_state(child, value, |b, v| b.set_value(*v))
}
#[property(CONTEXT)]
pub fn value_text(child: impl UiNode, value: impl IntoVar<Txt>) -> impl UiNode {
with_access_state(child, value, |b, v| b.set_value_text(v.clone()))
}
#[property(CONTEXT)]
pub fn col_count(child: impl UiNode, count: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, count, |b, v| b.set_col_count(*v))
}
#[property(CONTEXT)]
pub fn col_index(child: impl UiNode, index: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, index, |b, v| b.set_col_index(*v))
}
#[property(CONTEXT)]
pub fn col_span(child: impl UiNode, span: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, span, |b, v| b.set_col_span(*v))
}
#[property(CONTEXT)]
pub fn row_count(child: impl UiNode, count: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, count, |b, v| b.set_row_count(*v))
}
#[property(CONTEXT)]
pub fn row_index(child: impl UiNode, index: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, index, |b, v| b.set_row_index(*v))
}
#[property(CONTEXT)]
pub fn row_span(child: impl UiNode, span: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, span, |b, v| b.set_row_span(*v))
}
#[property(CONTEXT)]
pub fn item_count(child: impl UiNode, count: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, count, |b, v| b.set_item_count(*v))
}
#[property(CONTEXT)]
pub fn item_index(child: impl UiNode, index: impl IntoVar<usize>) -> impl UiNode {
with_access_state(child, index, |b, v| b.set_item_index(*v))
}
#[property(CONTEXT)]
pub fn modal(child: impl UiNode, modal: impl IntoVar<bool>) -> impl UiNode {
with_access_state(child, modal, |b, v| {
if *v {
b.flag_modal()
}
})
}
#[property(CONTEXT)]
pub fn controls(child: impl UiNode, controlled: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, controlled, |b, v| {
for id in v {
b.push_controls(*id);
}
})
}
#[property(CONTEXT)]
pub fn described_by(child: impl UiNode, descriptors: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, descriptors, |b, v| {
for id in v {
b.push_described_by(*id);
}
})
}
#[property(CONTEXT)]
pub fn details(child: impl UiNode, details: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, details, |b, v| {
for id in v {
b.push_details(*id);
}
})
}
#[property(CONTEXT)]
pub fn labelled_by(child: impl UiNode, labels: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, labels, |b, v| {
for id in v {
b.push_labelled_by(*id);
}
})
}
#[property(CONTEXT)]
pub fn owns(child: impl UiNode, owned: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, owned, |b, v| {
for id in v {
b.push_owns(*id);
}
})
}
#[property(CONTEXT)]
pub fn flows_to(child: impl UiNode, next_options: impl IntoVar<Vec<WidgetId>>) -> impl UiNode {
with_access_state(child, next_options, |b, v| {
for id in v {
b.push_flows_to(*id);
}
})
}
#[property(CONTEXT)]
pub fn invalid(child: impl UiNode, error: impl IntoVar<Invalid>) -> impl UiNode {
with_access_state(child, error, |b, v| b.set_invalid(*v))
}
#[property(CONTEXT)]
pub fn lang(child: impl UiNode, lang: impl IntoVar<Lang>) -> impl UiNode {
with_access_state(child, lang, |b, v| b.set_lang(v.0.clone()))
}
#[property(CONTEXT)]
pub fn scroll_horizontal(child: impl UiNode, normal_x: impl IntoVar<Factor>) -> impl UiNode {
with_access_state_var(child, normal_x, |b, v| b.set_scroll_horizontal(v.clone()))
}
#[property(CONTEXT)]
pub fn scroll_vertical(child: impl UiNode, normal_y: impl IntoVar<Factor>) -> impl UiNode {
with_access_state_var(child, normal_y, |b, v| b.set_scroll_vertical(v.clone()))
}
#[property(CONTEXT)]
pub fn live(
child: impl UiNode,
indicator: impl IntoVar<LiveIndicator>,
atomic: impl IntoVar<bool>,
busy: impl IntoVar<bool>,
) -> impl UiNode {
let indicator = indicator.into_var();
let atomic = atomic.into_var();
let busy = busy.into_var();
let mut handles = VarHandles::dummy();
match_node(child, move |c, op| match op {
UiNodeOp::Deinit => {
handles.clear();
}
UiNodeOp::Info { info } => {
c.info(info);
if let Some(mut builder) = info.access() {
if handles.is_dummy() {
handles.push(indicator.subscribe(UpdateOp::Info, WIDGET.id()));
handles.push(atomic.subscribe(UpdateOp::Info, WIDGET.id()));
handles.push(busy.subscribe(UpdateOp::Info, WIDGET.id()));
}
builder.set_live(indicator.get(), atomic.get(), busy.get());
}
}
_ => {}
})
}
fn with_access_state<T: VarValue>(
child: impl UiNode,
state: impl IntoVar<T>,
set_info: impl Fn(&mut WidgetAccessInfoBuilder, &T) + Send + 'static,
) -> impl UiNode {
with_access_state_var(child, state, move |b, v| v.with(|v| set_info(b, v)))
}
fn with_access_state_var<T: VarValue, I: IntoVar<T>>(
child: impl UiNode,
state: I,
set_info: impl Fn(&mut WidgetAccessInfoBuilder, &I::Var) + Send + 'static,
) -> impl UiNode {
let state = state.into_var();
let mut handle = VarHandle::dummy();
match_node(child, move |c, op| match op {
UiNodeOp::Deinit => {
handle = VarHandle::dummy();
}
UiNodeOp::Info { info } => {
c.info(info);
if let Some(mut builder) = info.access() {
if handle.is_dummy() {
handle = state.subscribe(UpdateOp::Info, WIDGET.id());
}
set_info(&mut builder, &state)
}
}
_ => {}
})
}