use iced::{
Element, Length,
widget::{column, container, mouse_area, row, space, stack},
};
use snora_core::{AppLayout, LayoutDirection};
use crate::overlay::{dialog::render_dialog, sheet::render_sheet};
use crate::toast::render_toasts;
pub fn render<'a, Message>(layout: AppLayout<Element<'a, Message>, Message>) -> Element<'a, Message>
where
Message: Clone + 'a,
{
let skeleton = build_skeleton(
layout.direction,
layout.header,
layout.side_bar,
layout.body,
layout.footer,
);
let mut layers = stack![skeleton];
let has_menu = layout.header_menu.is_some() || layout.context_menu.is_some();
if has_menu {
if let Some(on_close) = layout.on_close_menus {
layers = layers.push(transparent_backdrop(on_close));
}
if let Some(header_menu) = layout.header_menu {
layers = layers.push(header_menu);
}
if let Some(context_menu) = layout.context_menu {
layers = layers.push(context_menu);
}
}
let has_modal = layout.dialog.is_some() || layout.sheet.is_some();
if has_modal {
if let Some(on_close) = layout.on_close_modals {
layers = layers.push(dim_backdrop(on_close));
} else {
layers = layers.push(dim_without_capture());
}
if let Some(dialog) = layout.dialog {
layers = layers.push(render_dialog(dialog));
}
if let Some(sheet) = layout.sheet {
layers = layers.push(render_sheet(sheet, layout.direction));
}
}
if let Some(toast_layer) =
render_toasts(layout.toasts, layout.toast_position, layout.direction)
{
layers = layers.push(toast_layer);
}
layers.into()
}
fn build_skeleton<'a, Message>(
direction: LayoutDirection,
header: Option<Element<'a, Message>>,
side_bar: Option<Element<'a, Message>>,
body: Element<'a, Message>,
footer: Option<Element<'a, Message>>,
) -> Element<'a, Message>
where
Message: Clone + 'a,
{
let mut main_col = column![];
if let Some(header) = header {
main_col = main_col.push(header);
}
let body_container = container(body).width(Length::Fill).height(Length::Fill);
let body_row = match (direction, side_bar) {
(LayoutDirection::Ltr, Some(sb)) => row![sb, body_container],
(LayoutDirection::Rtl, Some(sb)) => row![body_container, sb],
(_, None) => row![body_container],
}
.width(Length::Fill)
.height(Length::Fill);
main_col = main_col.push(body_row);
if let Some(footer) = footer {
main_col = main_col.push(footer);
}
container(main_col)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
fn transparent_backdrop<'a, Message>(on_press: Message) -> Element<'a, Message>
where
Message: Clone + 'a,
{
mouse_area(container(space()).width(Length::Fill).height(Length::Fill))
.on_press(on_press)
.into()
}
fn dim_backdrop<'a, Message>(on_press: Message) -> Element<'a, Message>
where
Message: Clone + 'a,
{
use iced::{Background, Color, widget::container::Style};
let dim = container(space())
.width(Length::Fill)
.height(Length::Fill)
.style(|_theme| Style {
background: Some(Background::Color(Color::from_rgba(0.0, 0.0, 0.0, 0.4))),
..Default::default()
});
mouse_area(dim).on_press(on_press).into()
}
fn dim_without_capture<'a, Message>() -> Element<'a, Message>
where
Message: 'a,
{
use iced::{Background, Color, widget::container::Style};
container(space())
.width(Length::Fill)
.height(Length::Fill)
.style(|_theme| Style {
background: Some(Background::Color(Color::from_rgba(0.0, 0.0, 0.0, 0.4))),
..Default::default()
})
.into()
}