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()
}
}
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()
}
}
➡️ Next: From Sandbox To Application
📘 Back: Table of contents