feat: focusable segmented items in segmented button

This commit is contained in:
Michael Aaron Murphy 2023-01-09 16:18:02 +01:00 committed by Michael Murphy
parent a89ec01297
commit 29c7444a30
14 changed files with 794 additions and 611 deletions

View file

@ -12,9 +12,8 @@ use cosmic::{
iced_winit::window::{close, drag, minimize, toggle_maximize},
theme::{self, Theme},
widget::{
header_bar, icon, list, nav_bar, nav_button, scrollable,
segmented_button::{self, cosmic::vertical_view_switcher, SingleSelect},
settings,
header_bar, icon, list, nav_bar, nav_button, scrollable, segmented_button, settings,
IconSource,
},
Element, ElementExt,
};
@ -136,7 +135,7 @@ pub struct Window {
debug: bool,
demo: demo::State,
desktop: desktop::State,
nav_bar_pages: segmented_button::State<SingleSelect, Page>,
nav_bar_pages: segmented_button::SingleSelectModel<Page>,
nav_bar_toggled_condensed: bool,
nav_bar_toggled: bool,
page: Page,
@ -190,6 +189,21 @@ impl From<Page> for Message {
}
impl Window {
/// Adds a page to the model we use for the navigation bar.
fn insert_page(&mut self, page: Page) -> segmented_button::Key {
self.nav_bar_pages.insert(
segmented_button::item()
.text(page.title())
.icon(IconSource::Name(page.icon_name().into())),
page,
)
}
/// Activates the page by its key.
fn activate_page(&mut self, page: segmented_button::Key) {
self.nav_bar_pages.activate(page);
}
fn page_title<Message: 'static>(&self, page: Page) -> Element<Message> {
row!(text(page.title()).size(30), horizontal_space(Length::Fill),).into()
}
@ -291,29 +305,22 @@ impl Application for Window {
window.title = String::from("COSMIC Design System - Iced");
let mut add_page = |page: Page| {
let content = segmented_button::Content::default()
.text(page.title())
.icon(page.icon_name());
window.nav_bar_pages.insert(content, page)
};
add_page(Page::Demo);
add_page(Page::WiFi);
add_page(Page::Networking(None));
add_page(Page::Bluetooth);
let key = add_page(Page::Desktop(None));
add_page(Page::InputDevices(None));
add_page(Page::Displays);
add_page(Page::PowerAndBattery);
add_page(Page::Sound);
add_page(Page::PrintersAndScanners);
add_page(Page::PrivacyAndSecurity);
add_page(Page::SystemAndAccounts(None));
add_page(Page::TimeAndLanguage(None));
add_page(Page::Accessibility);
add_page(Page::Applications);
window.nav_bar_pages.activate(key);
window.insert_page(Page::Demo);
window.insert_page(Page::WiFi);
window.insert_page(Page::Networking(None));
window.insert_page(Page::Bluetooth);
let key = window.insert_page(Page::Desktop(None));
window.insert_page(Page::InputDevices(None));
window.insert_page(Page::Displays);
window.insert_page(Page::PowerAndBattery);
window.insert_page(Page::Sound);
window.insert_page(Page::PrintersAndScanners);
window.insert_page(Page::PrivacyAndSecurity);
window.insert_page(Page::SystemAndAccounts(None));
window.insert_page(Page::TimeAndLanguage(None));
window.insert_page(Page::Accessibility);
window.insert_page(Page::Applications);
window.activate_page(key);
(window, Command::none())
}
@ -364,7 +371,7 @@ impl Application for Window {
let mut ret = Command::none();
match message {
Message::NavBar(key) => {
if let Some(page) = self.nav_bar_pages.data(key).cloned() {
if let Some(page) = self.nav_bar_pages.component(key).cloned() {
self.nav_bar_pages.activate(key);
self.page(page);
}

View file

@ -5,7 +5,13 @@ use cosmic::{
theme::{Button as ButtonTheme, Theme},
widget::{
button,
segmented_button::{MultiSelect, SingleSelect},
segmented_button::{
self,
cosmic::{
horizontal_segmented_selection, horizontal_view_switcher,
vertical_segmented_selection, vertical_view_switcher,
},
},
settings,
spin_button::{SpinButtonModel, SpinMessage},
toggler,
@ -14,13 +20,6 @@ use cosmic::{
};
use super::{Page, Window};
use cosmic::widget::segmented_button::{
self,
cosmic::{
horizontal_segmented_selection, horizontal_view_switcher, vertical_segmented_selection,
vertical_view_switcher,
},
};
pub enum DemoView {
TabA,
@ -28,6 +27,7 @@ pub enum DemoView {
TabC,
}
#[allow(dead_code)]
pub enum MultiOption {
OptionA,
OptionB,
@ -60,14 +60,14 @@ pub enum Output {
pub struct State {
pub checkbox_value: bool,
pub icon_theme: segmented_button::State<SingleSelect, &'static str>,
pub multi_selection: segmented_button::State<MultiSelect, MultiOption>,
pub icon_theme: segmented_button::SingleSelectModel<&'static str>,
pub multi_selection: segmented_button::MultiSelectModel<MultiOption>,
pub pick_list_selected: Option<&'static str>,
pub selection: segmented_button::State<SingleSelect, ()>,
pub selection: segmented_button::SingleSelectModel<()>,
pub slider_value: f32,
pub spin_button: SpinButtonModel<i32>,
pub toggler_value: bool,
pub view_switcher: segmented_button::State<SingleSelect, DemoView>,
pub view_switcher: segmented_button::SingleSelectModel<DemoView>,
}
impl Default for State {
@ -78,23 +78,23 @@ impl Default for State {
slider_value: 50.0,
spin_button: SpinButtonModel::default().min(-10).max(10),
toggler_value: false,
icon_theme: segmented_button::State::builder()
icon_theme: segmented_button::Model::builder()
.insert_active("Pop", "Pop")
.insert("Adwaita", "Adwaita")
.build(),
selection: segmented_button::State::builder()
selection: segmented_button::Model::builder()
.insert_active("Choice A", ())
.insert("Choice B", ())
.insert("Choice C", ())
.build(),
multi_selection: segmented_button::State::builder()
.insert("Option A", MultiOption::OptionA)
multi_selection: segmented_button::Model::builder()
.insert_active("Option A", MultiOption::OptionA)
.insert("Option B", MultiOption::OptionB)
.insert("Option C", MultiOption::OptionC)
.insert("Option D", MultiOption::OptionD)
.insert("Option C", MultiOption::OptionB)
.insert("Option D", MultiOption::OptionC)
.insert("Option E", MultiOption::OptionE)
.build(),
view_switcher: segmented_button::State::builder()
view_switcher: segmented_button::Model::builder()
.insert_active("Controls", DemoView::TabA)
.insert("Segmented Button", DemoView::TabB)
.insert("Tab C", DemoView::TabC)
@ -120,7 +120,7 @@ impl State {
Message::ViewSwitcher(key) => self.view_switcher.activate(key),
Message::IconTheme(key) => {
self.icon_theme.activate(key);
if let Some(theme) = self.icon_theme.data(key) {
if let Some(theme) = self.icon_theme.component(key) {
cosmic::settings::set_default_icon_theme(*theme);
}
}
@ -150,7 +150,7 @@ impl State {
horizontal_view_switcher(&self.view_switcher)
.on_activate(Message::ViewSwitcher)
.into(),
match self.view_switcher.active_data() {
match self.view_switcher.active_component() {
None => panic!("no tab is active"),
Some(DemoView::TabA) => settings::view_column(vec![
settings::view_section("Debug")