Skip to content

Latest commit

 

History

History
164 lines (135 loc) · 4.16 KB

navigation_history.md

File metadata and controls

164 lines (135 loc) · 4.16 KB

Navigation History

This tutorial follows the previous tutorial. The framework introduced in the previous tutorial can be extended to handle page navigation history, which is capable of restoring past pages.

Instead of keeping a single page in the main struct MyApp, we can keep a Vec of pages. We control how the Vec would change in update method of SandBox. The communication between update of Sandbox and update of Page trait is through a custom enum Navigation.

use iced::{
    widget::{button, column, row, text},
    Sandbox, Settings,
};

fn main() -> iced::Result {
    MyApp::run(Settings::default())
}

#[derive(Debug, Clone)]
enum MyAppMessage {
    PageA(PageAMessage),
    PageB(PageBMessage),
}

enum Navigation {
    GoTo(Box<dyn Page>),
    Back,
    None,
}

trait Page {
    fn update(&mut self, message: MyAppMessage) -> Navigation;
    fn view(&self) -> iced::Element<MyAppMessage>;
}

struct MyApp {
    pages: Vec<Box<dyn Page>>,
}

impl Sandbox for MyApp {
    type Message = MyAppMessage;

    fn new() -> Self {
        Self {
            pages: vec![Box::new(PageA::new())],
        }
    }

    fn title(&self) -> String {
        String::from("My App")
    }

    fn update(&mut self, message: Self::Message) {
        let navigation = self.pages.last_mut().unwrap().update(message);
        match navigation {
            Navigation::GoTo(p) => self.pages.push(p),
            Navigation::Back => {
                if self.pages.len() > 1 {
                    self.pages.pop();
                }
            }
            Navigation::None => {}
        }
    }

    fn view(&self) -> iced::Element<Self::Message> {
        self.pages.last().unwrap().view()
    }
}

The following is the first type of pages:

#[derive(Debug, Clone)]
enum PageAMessage {
    ButtonPressed,
}
type Ma = PageAMessage;

struct PageA;

impl PageA {
    fn new() -> Self {
        Self
    }
}

impl Page for PageA {
    fn update(&mut self, message: MyAppMessage) -> Navigation {
        if let MyAppMessage::PageA(msg) = message {
            match msg {
                PageAMessage::ButtonPressed => {
                    return Navigation::GoTo(Box::new(PageB::new(1)));
                }
            }
        }
        Navigation::None
    }

    fn view(&self) -> iced::Element<MyAppMessage> {
        column![
            text("Start"),
            button("Next").on_press(MyAppMessage::PageA(Ma::ButtonPressed)),
        ]
        .into()
    }
}

Page A

And the second type of pages:

#[derive(Debug, Clone)]
enum PageBMessage {
    BackButtonPressed,
    NextButtonPressed,
}
type Mb = PageBMessage;

struct PageB {
    id: u32,
}

impl PageB {
    fn new(id: u32) -> Self {
        Self { id }
    }
}

impl Page for PageB {
    fn update(&mut self, message: MyAppMessage) -> Navigation {
        if let MyAppMessage::PageB(msg) = message {
            match msg {
                PageBMessage::BackButtonPressed => return Navigation::Back,
                PageBMessage::NextButtonPressed => {
                    return Navigation::GoTo(Box::new(PageB::new(self.id + 1)))
                }
            }
        }
        Navigation::None
    }

    fn view(&self) -> iced::Element<MyAppMessage> {
        column![
            text(self.id),
            row![
                button("Back").on_press(MyAppMessage::PageB(Mb::BackButtonPressed)),
                button("Next").on_press(MyAppMessage::PageB(Mb::NextButtonPressed)),
            ],
        ]
        .into()
    }
}

Page B

➡️ Next: From Sandbox To Application

📘 Back: Table of contents