beuvy 0.1.0

Facade crate for beuvy-runtime plus optional declarative UI authoring.
Documentation
use crate::DeclarativeEventKind;
use crate::runtime::state::{
    DeclarativeActionMessage, DeclarativeEventBindings, DeclarativeEventData,
    DeclarativeFormResetMessage, DeclarativeFormSubmitMessage, DeclarativeNodeId,
};
use beuvy_runtime::button::ButtonClickMessage;
use beuvy_runtime::input::InputValueChangedMessage;
use beuvy_runtime::link::LinkActivatedMessage;
use beuvy_runtime::select::SelectValueChangedMessage;
use bevy::prelude::*;
use bevy::ui::ScrollPosition;

fn write_bound_actions(
    entity: Entity,
    expected_kind: DeclarativeEventKind,
    event_data: impl Fn() -> DeclarativeEventData,
    bindings: &Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    actions: &mut MessageWriter<DeclarativeActionMessage>,
) {
    let Ok((node_id, event_bindings)) = bindings.get(entity) else {
        return;
    };

    for binding in event_bindings
        .0
        .iter()
        .filter(|binding| binding.kind == expected_kind)
    {
        actions.write(DeclarativeActionMessage {
            entity,
            node_id: node_id.0.clone(),
            kind: binding.kind,
            action_id: binding.action_id.clone(),
            params: binding.params.clone(),
            event_data: event_data(),
        });
    }
}

pub(crate) fn dispatch_activate_actions(
    button_clicks: Option<MessageReader<ButtonClickMessage>>,
    link_activations: Option<MessageReader<LinkActivatedMessage>>,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    if let Some(mut button_clicks) = button_clicks {
        for click in button_clicks.read() {
            write_bound_actions(
                click.entity,
                DeclarativeEventKind::Activate,
                || DeclarativeEventData::Activate,
                &bindings,
                &mut actions,
            );
        }
    }

    if let Some(mut link_activations) = link_activations {
        for activation in link_activations.read() {
            write_bound_actions(
                activation.entity,
                DeclarativeEventKind::Activate,
                || DeclarativeEventData::Activate,
                &bindings,
                &mut actions,
            );
        }
    }
}

pub(crate) fn dispatch_input_actions(
    input_changes: Option<MessageReader<InputValueChangedMessage>>,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    let Some(mut input_changes) = input_changes else {
        return;
    };
    for input in input_changes.read() {
        write_bound_actions(
            input.entity,
            DeclarativeEventKind::Input,
            || DeclarativeEventData::Input {
                value: input.value.clone(),
                runtime_value: input.runtime_value.clone(),
            },
            &bindings,
            &mut actions,
        );
        write_bound_actions(
            input.entity,
            DeclarativeEventKind::Change,
            || DeclarativeEventData::Change {
                value: input.value.clone(),
            },
            &bindings,
            &mut actions,
        );
    }
}

pub(crate) fn dispatch_select_change_actions(
    select_changes: Option<MessageReader<SelectValueChangedMessage>>,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    let Some(mut select_changes) = select_changes else {
        return;
    };
    for select in select_changes.read() {
        write_bound_actions(
            select.entity,
            DeclarativeEventKind::Change,
            || DeclarativeEventData::Change {
                value: select.value.clone(),
            },
            &bindings,
            &mut actions,
        );
    }
}

pub(crate) fn dispatch_wheel_actions(
    event: On<Pointer<bevy::picking::events::Scroll>>,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    write_bound_actions(
        event.entity,
        DeclarativeEventKind::Wheel,
        || DeclarativeEventData::Wheel {
            delta_x: event.x,
            delta_y: event.y,
            unit: event.unit,
        },
        &bindings,
        &mut actions,
    );
}

pub(crate) fn dispatch_scroll_actions(
    changed_scroll_positions: Query<
        (Entity, &ScrollPosition),
        (Changed<ScrollPosition>, With<DeclarativeEventBindings>, With<DeclarativeNodeId>),
    >,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    for (entity, scroll_position) in &changed_scroll_positions {
        write_bound_actions(
            entity,
            DeclarativeEventKind::Scroll,
            || DeclarativeEventData::Scroll {
                scroll_x: scroll_position.x,
                scroll_y: scroll_position.y,
            },
            &bindings,
            &mut actions,
        );
    }
}

pub(crate) fn dispatch_submit_reset_actions(
    submits: Option<MessageReader<DeclarativeFormSubmitMessage>>,
    resets: Option<MessageReader<DeclarativeFormResetMessage>>,
    bindings: Query<(&DeclarativeNodeId, &DeclarativeEventBindings)>,
    mut actions: MessageWriter<DeclarativeActionMessage>,
) {
    if let Some(mut submits) = submits {
        for submit in submits.read() {
            write_bound_actions(
                submit.entity,
                DeclarativeEventKind::Submit,
                || DeclarativeEventData::Submit {
                    values: submit.values.clone(),
                },
                &bindings,
                &mut actions,
            );
        }
    }

    if let Some(mut resets) = resets {
        for reset in resets.read() {
            write_bound_actions(
                reset.entity,
                DeclarativeEventKind::Reset,
                || DeclarativeEventData::Reset,
                &bindings,
                &mut actions,
            );
        }
    }
}