Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add derive macro for generating state structs #649

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jrmoulton
Copy link
Collaborator

A little proc macro to make it easier to model data as items that can be used in the UI

(would definitely make it conditional on a flag)

I think this is a nice convenient macro that encourages a good separation of regular application data and data that is to be displayed in a UI but I'm on the fence about including this.

Example of how this would be used:

#[derive(Clone, floem::State)]
#[state_derives(Clone, Copy, Eq, Debug)]
/// There is a `Todo` struct that doesn't have any signals or anything to do with the UI and could be built and used separately from the UI.
pub struct Todo {
    pub db_id: Option<i64>,
    #[state_skip]
    pub unique_id: u64,
    pub done: bool,
    pub description: String,
}
static UNIQUE_COUNTER: AtomicU64 = AtomicU64::new(0);
impl Todo {
    pub fn new_from_db(db_id: i64, done: bool, description: impl Into<String>) -> Self {
        Self {
            db_id: Some(db_id),
            unique_id: UNIQUE_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
            done,
            description: description.into(),
        }
    }
    pub fn new(done: bool, description: impl Into<String>) -> Self {
        Self {
            db_id: None,
            unique_id: UNIQUE_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
            done,
            description: description.into(),
        }
    }
}

/// The `TodoState` struct is generated and can be created by doing `todo.to_state()` and simply wraps the fields of `Todo` in signals and makes it easy to impl `IntoView`. 
///
/// This really isn't incredibly useful but it is nice, encourages a good separation, and removes a tedious task of manually creating signals.
impl IntoView for TodoState {
    type V = AnyView;

    fn into_view(self) -> Self::V {
    
        // At this point the `db_id`, `done`, and `description` are signals 
        // and are ready to be used for values that change over time in the UI.
    
        debounce_action(self.done, 300.millis(), move || {
            AppCommand::UpdateDone(self).execute()
        });

        debounce_action(self.description, 300.millis(), move || {
            AppCommand::UpdateDescription(self).execute()
        });

        let state = todo_state();
        let is_selected = create_memo(move |_| state.selected.with(|s| s.contains(&self)));
        let is_active =
            create_memo(move |_| state.active.with(|s| s.active.map_or(false, |v| v == self)));

        let input_focused = Trigger::new();
        let done_check = Checkbox::new_rw(self.done)
            .style(|s| {
                ...
            });

        let input = todo_input(self).into_view();
        let input_id = input.id();
        let input = input
            .disable_default_event(move || (EventListener::PointerDown, !is_active))
            .style(move |s| {
                ...
            });

        let main_controls = (done_check, input)
            .h_stack()
            .debug_name("Todo Checkbox and text input (main controls)")
            .style(|s| s.gap(10).width_full().items_center())
            .container()
            .style(|s| s.width_full().align_items(Some(AlignItems::FlexStart)));

        let container = main_controls.container();

        container
            .style(move |s| {
                ...
            })
            .into_any()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant