use rust_on_rails::prelude::*;
use crate::elements::shapes::{Rectangle};
use crate::elements::images::Brand;
use crate::events::{NavigateEvent, NavigatorSelect};
use crate::layout::{Column, Stack, Bin, Row, Padding, Offset, Size};
use crate::components::avatar::AvatarContent;
use crate::components::button::{Button, ButtonState};
use crate::{PelicanUI, Callback};
use crate::AppPage;
use crate::ElementID;
use std::fmt::Debug;
use super::NavigationButton;
#[derive(Debug, Component)]
pub struct DesktopInterface (Row, Option<DesktopNavigator>, Bin<Stack, Rectangle>, Box<dyn AppPage>);
impl DesktopInterface {
pub fn new(
ctx: &mut Context,
start_page: impl AppPage,
start_index: Option<usize>,
navigation: Option<Vec<(&'static str, &'static str, Box<Callback>)>>,
profile: Option<(&'static str, AvatarContent, Box<Callback>)>,
) -> Self {
let color = ctx.get::<PelicanUI>().theme.colors.outline.secondary;
let navigator = navigation.zip(profile).zip(start_index).map(|((nav, p), i)| DesktopNavigator::new(ctx, i, nav, p));
DesktopInterface(
Row(0.0, Offset::Start, Size::Fit, Padding::default()),
navigator,
Bin (
Stack(Offset::default(), Offset::default(), Size::Static(1.0), Size::Fit, Padding::default()),
Rectangle::new(color)
),
Box::new(start_page)
)
}
}
impl OnEvent for DesktopInterface {
fn on_event(&mut self, ctx: &mut Context, event: &mut dyn Event) -> bool {
if let Some(NavigateEvent(page)) = event.downcast_ref::<NavigateEvent>() {
self.3 = page.get_page(ctx);
}
true
}
}
#[derive(Debug, Component)]
pub struct DesktopNavigator(Column, Image, ButtonColumn, Bin<Stack, Rectangle>, NavigationButton);
impl DesktopNavigator {
pub fn new(
ctx: &mut Context,
start_index: usize,
navigation: Vec<(&'static str, &'static str, Box<Callback>)>,
mut profile: (&'static str, AvatarContent, Box<Callback>)
) -> Self {
if navigation.is_empty() {panic!("DesktopNavigator: Parameter 1 was empty. Navigator has no data.")}
let theme = &ctx.get::<PelicanUI>().theme;
let (wordmark, color) = (theme.brand.wordmark.clone(), theme.colors.shades.transparent);
let profile_id = ElementID::new();
let tabs: Vec<NavigationButton> = navigation.into_iter().enumerate().map(|(y, (i, n, mut c))| {
let id = ElementID::new();
let nb = Button::navigation(ctx, i, n, y == start_index, move |ctx: &mut Context| {
ctx.trigger_event(NavigatorSelect(id));
(c)(ctx);
});
NavigationButton::new(id, Some(nb), None)
}).collect();
let pb = Button::photo(ctx, profile.0, profile.1, false, move |ctx: &mut Context| {
ctx.trigger_event(NavigatorSelect(profile_id));
(profile.2)(ctx);
});
DesktopNavigator(
Column::new(32.0, Offset::Center, Size::Fill(100.0, 200.0), Padding(16.0, 32.0, 16.0, 32.0)),
Brand::new(wordmark, (80.0, 44.0)),
ButtonColumn::new(tabs),
Bin (
Stack(Offset::Center, Offset::Center, Size::Fill(100.0, 200.0), Size::Fill(100.0, f32::MAX), Padding::default()),
Rectangle::new(color)
),
NavigationButton::new(profile_id, Some(pb), None)
)
}
}
impl OnEvent for DesktopNavigator {
fn on_event(&mut self, ctx: &mut Context, event: &mut dyn Event) -> bool {
if let Some(NavigatorSelect(id)) = event.downcast_ref::<NavigatorSelect>() {
println!("Navigator selected");
let mut buttons: Vec<&mut NavigationButton> = self.2.buttons().iter_mut().collect(); buttons.push(&mut self.4);
buttons.iter_mut().for_each(|button| {
*button.button().as_mut().unwrap().status() = if button.id() == *id {ButtonState::Selected} else {ButtonState::Default};
button.button().as_mut().unwrap().color(ctx);
});
}
true
}
}
#[derive(Debug, Component)]
struct ButtonColumn(Column, Vec<NavigationButton>);
impl OnEvent for ButtonColumn {}
impl ButtonColumn {
fn new(buttons: Vec<NavigationButton>) -> Self {
ButtonColumn(Column::center(8.0), buttons)
}
fn buttons(&mut self) -> &mut Vec<NavigationButton> {&mut self.1}
}