// Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only mod binder; pub use binder::{AutoBind, Binder}; mod insert; use cosmic::{Element, Task}; use downcast_rs::{Downcast, impl_downcast}; pub use insert::Insert; pub mod section; pub use section::Section; use derive_setters::Setters; use slotmap::SlotMap; use std::borrow::Cow; slotmap::new_key_type! { /// The unique ID of a page. pub struct Entity; } /// A collection of sections which a page may be comprised of. pub type Content = Vec; pub trait Page: Downcast { /// Information about the page fn info(&self) -> Info; /// Initialize the sections used by this page. #[must_use] #[inline] fn content( &self, _sections: &mut SlotMap>, ) -> Option { None } /// Display a context drawer for the page. #[must_use] #[inline] fn context_drawer(&self) -> Option> { None } /// Set a custom page header #[inline] fn header(&self) -> Option> { None } /// Display an inner app dialog for the page. #[inline] fn dialog(&self) -> Option> { None } /// Response from a file chooser dialog request. #[inline] fn file_chooser(&mut self, _selected: Vec) -> Task { Task::none() } /// Alter the contents of the page's header view. #[inline] fn header_view(&self) -> Option> { None } /// Emit on the context drawer being closed #[allow(unused)] #[inline] fn on_context_drawer_close(&mut self) -> Task { Task::none() } /// Reload page metadata via a Task. #[allow(unused)] #[inline] fn on_enter(&mut self) -> Task { Task::none() } /// Emit a command when the page is left #[inline] fn on_leave(&mut self) -> Task { Task::none() } /// Assigns the entity ID of the page to the page. #[allow(unused)] #[inline] fn set_id(&mut self, entity: Entity) {} /// The title to display in the page header. #[inline] fn title(&self) -> Option<&str> { None } } impl_downcast!(Page); /// Information about a page; including its title, icon, and description. #[derive(Setters)] #[must_use] pub struct Info { /// An identifier that is the same between application runs. #[setters(skip)] pub id: Cow<'static, str>, /// The icon associated with the page. #[setters(skip)] pub icon_name: Cow<'static, str>, /// The title of the page. #[setters(into)] pub title: String, /// A description of the page. #[setters(into)] pub description: String, /// The parent of the page. #[setters(strip_option)] pub parent: Option, } impl Info { #[inline] pub fn new(id: impl Into>, icon_name: impl Into>) -> Self { Self { title: String::new(), icon_name: icon_name.into(), id: id.into(), description: String::new(), parent: None, } } } #[macro_export] macro_rules! update { ($binder:expr, $message:expr, $page:ty) => {{ #[allow(unused_must_use)] if let Some(page) = $binder.page_mut::<$page>() { page.update($message); } }}; }