use crate::message_navigation; use crate::state_update; use crate::view_navigation; use std::sync::{Arc, Mutex}; use iced::{Element, Task}; use iced::keyboard::Event; use crate::{fill_state, AppState }; use crate::data_provider::sqlite::create_db; use crate::dictionary::{DictionaryMessage, DictionaryState}; use crate::dictionary_test::{DictionaryQuizMessage, DictionaryQuizState}; use crate::history::{HistoryMessage, HistoryState}; use crate::navigation::Page::*; use crate::navigation::RootMessage::Keyboard; use crate::quiz::{QuizMessage, QuizState}; use crate::randomizer::randomizer::{RandomizerMessage, RandomizerState}; use crate::repetition::{RepetitionMessage, RepetitionState}; use crate::repetitions::{RepetitionsMessage, RepetitionsState}; use crate::selector::{SelectorMessage, SelectorState}; use crate::sync::{SyncMessage, SyncState}; use crate::word::{WordMessage, WordState}; use crate::writing::{WritingMessage, WritingState}; impl Default for ScreenState { fn default() -> Self { let mut state = AppState::new(); fill_state(&mut state); let state = Arc::new(Mutex::new(state)); ScreenState { stack: vec![Page::Selector(SelectorState::new(state.clone()))], } } } #[derive(Clone)] pub enum RootMessage { Selector(SelectorMessage), Quiz(QuizMessage), Writing(WritingMessage), Dictionary(DictionaryMessage), DictionaryQuiz(DictionaryQuizMessage), Randomizer(RandomizerMessage), Repetitions(RepetitionsMessage), Repetition(RepetitionMessage), Word(WordMessage), Sync(SyncMessage), History(HistoryMessage), Keyboard(Event), } pub enum Page { Selector(SelectorState), Quiz(QuizState), Writing(WritingState), Dictionary(DictionaryState), DictionaryQuiz(DictionaryQuizState), Randomizer(RandomizerState), Repetitions(RepetitionsState), Repetition(RepetitionState), Word(WordState), Sync(SyncState), History(HistoryState), PreviousPage, } pub struct ScreenState { stack: Vec, } impl ScreenState { pub fn boot() -> (ScreenState, Task) { create_db(); (ScreenState::default(), Task::none()) } pub fn update(&mut self, message: RootMessage) -> Task { if let Keyboard(e) = message { return self.handle_keyboard(e); } state_update!( message, self.stack, Selector, Quiz, Writing, Dictionary, DictionaryQuiz, Randomizer, Repetitions, Repetition, Word, Sync, History ); Task::none() } pub fn view(&self) -> Element<'_, RootMessage> { view_navigation!( self.stack, Quiz, Selector, Writing, Dictionary, DictionaryQuiz, Randomizer, Repetitions, Repetition, Word, Sync, History ) } fn handle_keyboard(&mut self, message: Event) -> Task { let page = self.stack.last_mut().unwrap(); match page { Page::Repetition(page) => page.press(&message), _ => Task::none(), } } } pub struct AppSettings { pub(crate) key: Option, } #[macro_export] macro_rules! view_navigation { ($stack:expr, $($e:ident), *) => { match &$stack.last().unwrap() { $( $e(s) => s.view().map(RootMessage::$e), )* _ => iced::widget::space().into(), } } } #[macro_export] macro_rules! state_update { ($message:expr, $stack:expr, $($e:ident), *) => { match $message { $( RootMessage::$e(msg) => { if let $e(s) = $stack.last_mut().unwrap() { message_navigation!(msg, $stack, s) } } )* _ => {} } } } #[macro_export] macro_rules! message_navigation { ($msg:expr, $stack:expr, $state:expr) => { if let Some(new_page) = $state.navigate(&$msg) { if let Page::PreviousPage = new_page { $stack.pop(); return Task::none(); } $stack.push(new_page); } else { return $state.update($msg); } }; } pub trait NavigatedPage { fn navigate(&self, message: &T) -> Option; } pub trait KeyPressedPage { fn press(&mut self, message: &Event) -> Task; }