Add input settings, with mouse, keyboard, keyboard shortcuts sub-pages
Still needs to be integrated with compositor so it actually works, need touchpad page, etc.
This commit is contained in:
parent
a4c567a954
commit
2a77cdacb4
10 changed files with 526 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -783,6 +783,7 @@ dependencies = [
|
|||
"cosmic-settings-page",
|
||||
"cosmic-settings-system",
|
||||
"cosmic-settings-time",
|
||||
"derivative",
|
||||
"derive_setters",
|
||||
"dirs 5.0.1",
|
||||
"downcast-rs",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ cosmic-settings-desktop = { path = "../pages/desktop" }
|
|||
cosmic-settings-page = { path = "../page" }
|
||||
cosmic-settings-system = { path = "../pages/system" }
|
||||
cosmic-settings-time = { path = "../pages/time" }
|
||||
derivative = "2.2.0"
|
||||
derive_setters = "0.1.6"
|
||||
dirs = "5.0.1"
|
||||
generator = "0.7.4"
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use crate::{
|
|||
applets::{self, APPLET_DND_ICON_ID},
|
||||
},
|
||||
},
|
||||
sound, system, time,
|
||||
input, sound, system, time,
|
||||
},
|
||||
subscription::desktop_files,
|
||||
widget::{page_title, parent_page_button, search_header, sub_page_button},
|
||||
|
|
@ -142,6 +142,8 @@ impl Application for SettingsApp {
|
|||
|
||||
// app.insert_page::<accessibility::Page>();
|
||||
// app.insert_page::<applications::Page>();
|
||||
//
|
||||
app.insert_page::<input::Page>();
|
||||
|
||||
let active_id = app
|
||||
.pages
|
||||
|
|
@ -268,6 +270,16 @@ impl Application for SettingsApp {
|
|||
crate::pages::Message::DesktopWallpaper(message) => {
|
||||
page::update!(self.pages, message, desktop::wallpaper::Page);
|
||||
}
|
||||
crate::pages::Message::Input(message) => {
|
||||
if matches!(message, input::Message::OpenKeyboardShortcuts) {
|
||||
if let Some(id) = self.pages.page_id::<input::keyboard::shortcuts::Page>() {
|
||||
self.activate_page(id);
|
||||
}
|
||||
}
|
||||
if let Some(page) = self.pages.page_mut::<input::Page>() {
|
||||
page.update(message);
|
||||
}
|
||||
}
|
||||
crate::pages::Message::External { .. } => {
|
||||
todo!("external plugins not supported yet");
|
||||
}
|
||||
|
|
|
|||
201
app/src/pages/input/keyboard/mod.rs
Normal file
201
app/src/pages/input/keyboard/mod.rs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
use apply::Apply;
|
||||
use cosmic::iced::{
|
||||
self,
|
||||
widget::{self, horizontal_space},
|
||||
Length,
|
||||
};
|
||||
use cosmic::iced_style;
|
||||
use cosmic::widget::settings;
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
use super::Message;
|
||||
|
||||
fn popover_menu_row(label: String) -> cosmic::Element<'static, Message> {
|
||||
widget::text(label)
|
||||
.apply(widget::container)
|
||||
.style(cosmic::theme::Container::custom(|theme| {
|
||||
iced_style::container::Appearance {
|
||||
background: None,
|
||||
..cosmic::widget::list::column::style(theme)
|
||||
}
|
||||
}))
|
||||
.apply(widget::button)
|
||||
.style(cosmic::theme::Button::Transparent)
|
||||
.into()
|
||||
}
|
||||
|
||||
// TODO for on press, would need to clone ID for each row?
|
||||
fn popover_menu() -> cosmic::Element<'static, Message> {
|
||||
// XXX translate
|
||||
widget::column![
|
||||
popover_menu_row(fl!("keyboard-sources", "move-up")),
|
||||
popover_menu_row(fl!("keyboard-sources", "move-down")),
|
||||
//cosmic::widget::divider::horizontal::light(),
|
||||
cosmic::widget::divider::horizontal::light(),
|
||||
popover_menu_row(fl!("keyboard-sources", "settings")),
|
||||
popover_menu_row(fl!("keyboard-sources", "view-layout")),
|
||||
popover_menu_row(fl!("keyboard-sources", "remove")),
|
||||
]
|
||||
.width(Length::Shrink)
|
||||
.height(Length::Shrink)
|
||||
.apply(cosmic::widget::container)
|
||||
.style(cosmic::theme::Container::custom(|theme| {
|
||||
iced_style::container::Appearance {
|
||||
text_color: Some(theme.cosmic().background.on.into()),
|
||||
background: Some(iced::Color::from(theme.cosmic().background.base).into()),
|
||||
border_radius: (12.0).into(),
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
}
|
||||
}))
|
||||
.into()
|
||||
}
|
||||
|
||||
fn popover_button(input_source: &InputSource, expanded: bool) -> cosmic::Element<'static, Message> {
|
||||
let style = if expanded {
|
||||
cosmic::theme::Svg::SymbolicActive
|
||||
} else {
|
||||
cosmic::theme::Svg::Symbolic
|
||||
};
|
||||
let on_press = Message::ExpandInputSourcePopover(if expanded {
|
||||
None
|
||||
} else {
|
||||
Some(input_source.id.clone())
|
||||
});
|
||||
let button = cosmic::widget::button(cosmic::theme::Button::Secondary)
|
||||
.icon(style, "open-menu-symbolic", 20)
|
||||
.padding(0)
|
||||
.on_press(on_press);
|
||||
|
||||
if expanded {
|
||||
cosmic::widget::popover(button, popover_menu()).into()
|
||||
} else {
|
||||
button.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn input_source<'a>(
|
||||
input_source: &'a InputSource,
|
||||
expanded_source_popover: Option<&'a str>,
|
||||
) -> cosmic::Element<'a, Message> {
|
||||
let expanded = expanded_source_popover == Some(input_source.id.as_str());
|
||||
settings::item(&input_source.label, popover_button(input_source, expanded)).into()
|
||||
}
|
||||
|
||||
pub mod shortcuts;
|
||||
|
||||
pub struct InputSource {
|
||||
id: String,
|
||||
// TODO Translate?
|
||||
label: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
// XXX
|
||||
pub fn default_input_sources() -> Vec<InputSource> {
|
||||
vec![InputSource {
|
||||
id: "us".to_string(),
|
||||
label: "English (US)".to_string(),
|
||||
}]
|
||||
}
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![
|
||||
sections.insert(input_sources()),
|
||||
sections.insert(special_character_entry()),
|
||||
sections.insert(keyboard_shortcuts()),
|
||||
])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("keyboard", "input-keyboard-symbolic")
|
||||
.title(fl!("keyboard"))
|
||||
.description(fl!("keyboard", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {
|
||||
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
|
||||
page.sub_page::<shortcuts::Page>()
|
||||
}
|
||||
}
|
||||
|
||||
fn input_sources() -> Section<crate::pages::Message> {
|
||||
// TODO desc
|
||||
Section::default()
|
||||
.title(fl!("keyboard-sources"))
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let input = binder.page::<super::Page>().expect("input page not found");
|
||||
|
||||
// TODO Need something more custom, with drag and drop
|
||||
let mut section = settings::view_section(§ion.title);
|
||||
|
||||
let expanded_source = input.expanded_source_popover.as_deref();
|
||||
for source in &input.sources {
|
||||
section = section.add(input_source(source, expanded_source));
|
||||
}
|
||||
|
||||
section
|
||||
.apply(cosmic::Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
|
||||
fn special_character_entry() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("keyboard-special-char"))
|
||||
.descriptions(vec![
|
||||
fl!("keyboard-special-char", "alternate"),
|
||||
fl!("keyboard-special-char", "compose"),
|
||||
])
|
||||
.view::<Page>(|_binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
// TODO dialogs
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(&descriptions[0], go_next_control()))
|
||||
.add(settings::item(&descriptions[1], go_next_control()))
|
||||
.apply(cosmic::Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
|
||||
fn keyboard_shortcuts() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("keyboard-shortcuts"))
|
||||
.descriptions(vec![fl!("keyboard-shortcuts", "desc")])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(
|
||||
settings::item(&descriptions[0], go_next_control())
|
||||
.apply(widget::container)
|
||||
.style(cosmic::theme::Container::custom(
|
||||
cosmic::widget::list::column::style,
|
||||
))
|
||||
.apply(widget::button)
|
||||
.style(cosmic::theme::Button::Transparent)
|
||||
.padding(0)
|
||||
.on_press(Message::OpenKeyboardShortcuts),
|
||||
)
|
||||
.apply(cosmic::Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
|
||||
fn go_next_control() -> cosmic::Element<'static, Message> {
|
||||
widget::row!(
|
||||
horizontal_space(Length::Fill),
|
||||
cosmic::widget::icon("go-next-symbolic", 20).style(cosmic::theme::Svg::Symbolic)
|
||||
)
|
||||
.into()
|
||||
}
|
||||
54
app/src/pages/input/keyboard/shortcuts.rs
Normal file
54
app/src/pages/input/keyboard/shortcuts.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use apply::Apply;
|
||||
use cosmic::iced::{
|
||||
widget::{self, horizontal_space},
|
||||
Length,
|
||||
};
|
||||
use cosmic::widget::settings;
|
||||
use cosmic::Element;
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
//crate::app::Message::Page
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(shortcuts())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("keyboard-shortcuts", "input-keyboard-symbolic")
|
||||
.title(fl!("keyboard-shortcuts"))
|
||||
.description(fl!("keyboard-shortcuts", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
||||
fn shortcuts() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.descriptions(vec![])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
let input = binder
|
||||
.page::<super::super::Page>()
|
||||
.expect("input page not found");
|
||||
|
||||
// TODO need something more custom
|
||||
/*
|
||||
settings::view_section(§ion.title)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
*/
|
||||
widget::column![settings::view_section(§ion.title)]
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
81
app/src/pages/input/mod.rs
Normal file
81
app/src/pages/input/mod.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use cosmic_settings_page as page;
|
||||
|
||||
pub mod keyboard;
|
||||
mod mouse;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
SetAcceleration(bool),
|
||||
SetNaturalScroll(bool),
|
||||
SetScrollSpeed(u32),
|
||||
SetDoubleClickSpeed(u32),
|
||||
SetMouseSpeed(u32),
|
||||
PrimaryButtonSelected(cosmic::widget::segmented_button::Entity),
|
||||
// seperate close message, to make sure another isn't closed?
|
||||
ExpandInputSourcePopover(Option<String>),
|
||||
OpenKeyboardShortcuts,
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Default)]
|
||||
pub struct Page {
|
||||
// Mouse
|
||||
#[derivative(Default(value = "mouse::default_primary_button()"))]
|
||||
primary_button: cosmic::widget::segmented_button::SingleSelectModel,
|
||||
acceleration: bool,
|
||||
natural_scroll: bool,
|
||||
double_click_speed: u32,
|
||||
scroll_speed: u32,
|
||||
mouse_speed: u32,
|
||||
|
||||
// Keyboard
|
||||
expanded_source_popover: Option<String>,
|
||||
#[derivative(Default(value = "keyboard::default_input_sources()"))]
|
||||
sources: Vec<keyboard::InputSource>,
|
||||
}
|
||||
|
||||
impl Page {
|
||||
// TODO
|
||||
pub fn update(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::SetAcceleration(value) => {
|
||||
self.acceleration = value;
|
||||
}
|
||||
Message::SetNaturalScroll(value) => {
|
||||
self.natural_scroll = value;
|
||||
}
|
||||
Message::SetScrollSpeed(value) => {
|
||||
self.scroll_speed = value;
|
||||
}
|
||||
Message::SetDoubleClickSpeed(value) => {
|
||||
self.double_click_speed = value;
|
||||
}
|
||||
Message::SetMouseSpeed(value) => {
|
||||
self.mouse_speed = value;
|
||||
}
|
||||
Message::PrimaryButtonSelected(entity) => {
|
||||
self.primary_button.activate(entity);
|
||||
}
|
||||
Message::ExpandInputSourcePopover(value) => {
|
||||
self.expanded_source_popover = value;
|
||||
}
|
||||
// TODO Specially handled in app.rs
|
||||
Message::OpenKeyboardShortcuts => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn info(&self) -> page::Info {
|
||||
// XXX icon?
|
||||
page::Info::new("input", "input-keyboard-symbolic")
|
||||
.title(fl!("input"))
|
||||
.description(fl!("input", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {
|
||||
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
|
||||
page.sub_page::<keyboard::Page>().sub_page::<mouse::Page>()
|
||||
}
|
||||
}
|
||||
120
app/src/pages/input/mouse.rs
Normal file
120
app/src/pages/input/mouse.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
use apply::Apply;
|
||||
use cosmic::iced::{
|
||||
widget::{self, horizontal_space},
|
||||
Length,
|
||||
};
|
||||
use cosmic::widget::settings;
|
||||
use cosmic::Element;
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
use super::Message;
|
||||
|
||||
// XXX
|
||||
pub fn default_primary_button() -> cosmic::widget::segmented_button::SingleSelectModel {
|
||||
let mut model = cosmic::widget::segmented_button::SingleSelectModel::builder()
|
||||
.insert(|b| b.text(fl!("mouse", "primary-button-left")))
|
||||
.insert(|b| b.text(fl!("mouse", "primary-button-right")))
|
||||
.build();
|
||||
model.activate_position(0);
|
||||
model
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(mouse()), sections.insert(scrolling())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("mouse", "input-mouse-symbolic")
|
||||
.title(fl!("mouse"))
|
||||
.description(fl!("mouse", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
||||
fn mouse() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.descriptions(vec![
|
||||
fl!("mouse", "primary-button"),
|
||||
fl!("mouse", "speed"),
|
||||
fl!("mouse", "acceleration"),
|
||||
fl!("mouse", "acceleration-desc"),
|
||||
fl!("mouse", "double-click-speed"),
|
||||
fl!("mouse", "double-click-speed-desc"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
let input = binder.page::<super::Page>().expect("input page not found");
|
||||
|
||||
// TODO need something more custom
|
||||
settings::view_section(§ion.title)
|
||||
// TODO
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
cosmic::widget::segmented_selection::horizontal(&input.primary_button)
|
||||
.on_activate(Message::PrimaryButtonSelected),
|
||||
))
|
||||
.add(
|
||||
settings::item::builder(&descriptions[1]).control(widget::slider(
|
||||
0..=100,
|
||||
input.mouse_speed,
|
||||
Message::SetMouseSpeed,
|
||||
)),
|
||||
)
|
||||
.add(
|
||||
settings::item::builder(&descriptions[2])
|
||||
.description(&descriptions[3])
|
||||
.toggler(input.acceleration, Message::SetAcceleration),
|
||||
)
|
||||
.add(
|
||||
settings::item::builder(&descriptions[4])
|
||||
.description(&descriptions[5])
|
||||
.control(widget::slider(
|
||||
0..=100,
|
||||
input.double_click_speed,
|
||||
Message::SetDoubleClickSpeed,
|
||||
)),
|
||||
)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
|
||||
fn scrolling() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("mouse-scrolling"))
|
||||
.descriptions(vec![
|
||||
fl!("mouse-scrolling", "speed"),
|
||||
fl!("mouse-scrolling", "natural"),
|
||||
fl!("mouse-scrolling", "natural-desc"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
let input = binder.page::<super::Page>().expect("input page not found");
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
// TODO show numeric value
|
||||
widget::slider(0..=100, input.scroll_speed, Message::SetScrollSpeed),
|
||||
))
|
||||
.add(
|
||||
settings::item::builder(&descriptions[1])
|
||||
.description(&descriptions[2])
|
||||
.toggler(input.natural_scroll, Message::SetNaturalScroll),
|
||||
)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Input)
|
||||
})
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
use cosmic_settings_page::Entity;
|
||||
|
||||
pub mod desktop;
|
||||
pub mod input;
|
||||
pub mod networking;
|
||||
pub mod sound;
|
||||
pub mod system;
|
||||
|
|
@ -17,6 +18,7 @@ pub enum Message {
|
|||
Panel(desktop::panel::Message),
|
||||
DesktopWallpaper(desktop::wallpaper::Message),
|
||||
Applet(desktop::panel::applets::Message),
|
||||
Input(input::Message),
|
||||
External { id: String, message: Vec<u8> },
|
||||
Page(Entity),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,3 +221,49 @@ firmware = Firmware
|
|||
|
||||
users = Users
|
||||
.desc = Authentication and login, lock screen.
|
||||
|
||||
## Input
|
||||
|
||||
input = Input
|
||||
.desc = Input
|
||||
|
||||
## Input: Keyboard
|
||||
|
||||
keyboard = Keyboard
|
||||
.desc = Keyboard input
|
||||
|
||||
keyboard-sources = Input Sources
|
||||
.desc = Input sources can be switched using Super+Space key combination. This can be customized in the keyboard shortcut settings.
|
||||
.move-up = Move up
|
||||
.move-down = Move down
|
||||
.settings = Settings
|
||||
.view-layout = View keyboard layout
|
||||
.remove = Remove
|
||||
|
||||
keyboard-special-char = Special Character Entry
|
||||
.alternate = Alternate characters key
|
||||
.compose = Compose key
|
||||
|
||||
## Input: Keyboard: Shortcuts
|
||||
|
||||
keyboard-shortcuts = Keyboard Shortcuts
|
||||
.desc = View and customize shortcuts
|
||||
|
||||
## Input: Mouse
|
||||
mouse = Mouse
|
||||
.desc = Mouse speed, acceleration, natural scrolling.
|
||||
.primary-button = Primary button
|
||||
.primary-button-left = Left
|
||||
.primary-button-right = Right
|
||||
.speed = Mouse speed
|
||||
.acceleration = Enable mouse acceleration
|
||||
.acceleration-desc = Automatically adjusts tracking sensitivty based on speed.
|
||||
.double-click-speed = Double-click speed
|
||||
.double-click-speed-desc = Changes how fast double-clicks have to be to register.
|
||||
|
||||
mouse-scrolling = Scrolling
|
||||
.speed = Scrolling speed
|
||||
.natural = Natural scrolling
|
||||
.natural-desc = Scroll the content, instead of the view
|
||||
|
||||
## Input: Touchpad
|
||||
|
|
|
|||
|
|
@ -118,19 +118,22 @@ impl<Message: 'static> Binder<Message> {
|
|||
self.page.get_mut(id).map(AsMut::as_mut)
|
||||
}
|
||||
|
||||
/// Get entity ID of page by its type ID.
|
||||
pub fn page_id<P: Page<Message>>(&self) -> Option<crate::Entity> {
|
||||
self.typed_page_ids.get(&TypeId::of::<P>()).copied()
|
||||
}
|
||||
|
||||
/// Obtain a reference to a page by its type ID.
|
||||
#[must_use]
|
||||
pub fn page<P: Page<Message>>(&self) -> Option<&P> {
|
||||
let id = self.typed_page_ids.get(&TypeId::of::<P>())?;
|
||||
let page = self.page.get(*id)?;
|
||||
let page = self.page.get(self.page_id::<P>()?)?;
|
||||
page.downcast_ref::<P>()
|
||||
}
|
||||
|
||||
/// Obtain a reference to a page by its type ID.
|
||||
#[must_use]
|
||||
pub fn page_mut<P: Page<Message>>(&mut self) -> Option<&mut P> {
|
||||
let id = self.typed_page_ids.get(&TypeId::of::<P>())?;
|
||||
let page = self.page.get_mut(*id)?;
|
||||
let page = self.page.get_mut(self.page_id::<P>()?)?;
|
||||
page.downcast_mut::<P>()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue