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

How to use this inside a struct for my egui app. #47

Open
IAMSolaara opened this issue Jul 18, 2024 · 1 comment
Open

How to use this inside a struct for my egui app. #47

IAMSolaara opened this issue Jul 18, 2024 · 1 comment

Comments

@IAMSolaara
Copy link

Hello, I'm trying to use this crate to make my egui app's page navigation.

I have this in my app:

#[typestate]
mod page_navigator {
    #[automaton]
    pub struct Page {}

    #[state]
    pub struct FirstPage;
    #[state]
    pub struct SecondPage;

    pub trait FirstPage {
        fn init() -> FirstPage;
        fn next_page(self) -> SecondPage;
    }

    pub trait SecondPage {
        fn prev_page(self) -> FirstPage;
        fn close(self);
    }
}

impl FirstPageState for Page<FirstPage> {
    fn init() -> Page<FirstPage> {
        Self { state: FirstPage }
    }

    fn next_page(self) -> Page<SecondPage> {
        Page::<SecondPage> { state: SecondPage }
    }
}

impl SecondPageState for Page<SecondPage> {
    fn prev_page(self) -> Page<FirstPage> {
        Page::<FirstPage> { state: FirstPage }
    }

    fn close(self) {
    }
}

I want to put this inside my egui app's App struct:

#[tokio::main]
async fn main() -> eframe::Result {
    eframe::run_native(
        "page_test_app",
        eframe::NativeOptions::default(),
        Box::new(|_cc| Ok(Box::new(App::init()))),
    )
}

struct App {
    current_app_page: Page<FirstPage>,
}

impl App {
    pub fn init() -> Self {
        Self {
            current_app_page: Page::init(),
        }
    }
}

and so far it compiles fine. But obviously when I want to change the page I need to reassign the current_app_page field to the new transitioned state problems arise because of the field's type:

impl eframe::App for App {
    fn update(&mut self, ctx: &eframe::egui::Context, frame: &mut eframe::Frame) {
        eframe::egui::CentralPanel::default().show(ctx, |ui| {
            if ui.button("Next Page").clicked() {
                self.current_app_page = self.current_app_page.next_page();
            }
        });
    }
}

How do I go about this?

Should I make my whole App struct generic over my PageState?

I apologize for the quality of this issue but I really don't know what would be a good way to do this.

@jmg-duarte
Copy link
Contributor

jmg-duarte commented Jul 19, 2024

Hey @IAMSolaara, I am grateful you took the time to experiment with the crate! No worries about the issue quality, the project was developed as my MSc thesis and I'll be the first to admit it isn't production ready, maybe someday and issues like these definitely help!

Should I make my whole App struct generic over my PageState?

The answer is yes, there's really no other way about it. I know this has really big implications but it's an implicit issue that comes from the advantages of Rust's type system.

If I may ask, how did you find this crate?

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

No branches or pull requests

2 participants