improv(segmented-button): Documentation improvements with cosmic widget configurations

This commit is contained in:
Michael Aaron Murphy 2022-12-28 23:18:31 +01:00
parent d1fd209b23
commit 2e149fd054
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
5 changed files with 106 additions and 17 deletions

View file

@ -2,7 +2,7 @@ use cosmic::{
iced::widget::{checkbox, pick_list, progress_bar, radio, row, slider}, iced::widget::{checkbox, pick_list, progress_bar, radio, row, slider},
iced::{Alignment, Length}, iced::{Alignment, Length},
theme::{self, Button as ButtonTheme, Theme}, theme::{self, Button as ButtonTheme, Theme},
widget::{button, segmented_button, settings, toggler}, widget::{button, segmented_button::cosmic::{view_switcher, segmented_selection}, settings, toggler},
Element, Element,
}; };
@ -30,8 +30,7 @@ impl Window {
settings::view_column(vec![ settings::view_column(vec![
self.page_title(Page::Demo), self.page_title(Page::Demo),
segmented_button(&self.demo_view_switcher) view_switcher(&self.demo_view_switcher)
.height(Length::Units(48))
.on_activate(Message::DemoTabActivate) .on_activate(Message::DemoTabActivate)
.into(), .into(),
match self.demo_view_switcher.active_data() { match self.demo_view_switcher.active_data() {
@ -122,8 +121,7 @@ impl Window {
cosmic::iced::widget::text("SegmentedButton::Selection") cosmic::iced::widget::text("SegmentedButton::Selection")
.font(cosmic::font::FONT_SEMIBOLD) .font(cosmic::font::FONT_SEMIBOLD)
.into(), .into(),
segmented_button(&self.demo_selection) segmented_selection(&self.demo_selection)
.style(theme::SegmentedButton::Selection)
.on_activate(Message::DemoSelectionActivate) .on_activate(Message::DemoSelectionActivate)
.into() .into()
]) ])

View file

@ -0,0 +1,29 @@
// Copyright 2022 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0
use super::{SegmentedButton, State};
use iced_core::Length;
/// Appears as a collection of tabs for developing a tabbed interface.
///
/// The data for the widget comes from a [`State`] that is maintained the application.
#[must_use]
pub fn view_switcher<Message, Data>(
state: &State<Data>,
) -> SegmentedButton<Message, crate::Renderer> {
SegmentedButton::new(&state.inner)
.height(Length::Units(48))
.style(crate::theme::SegmentedButton::ViewSwitcher)
}
/// Appears as a selection of choices for choosing between.
///
/// The data for the widget comes from a [`State`] that is maintained the application.
#[must_use]
pub fn segmented_selection<Message, Data>(
state: &State<Data>,
) -> SegmentedButton<Message, crate::Renderer> {
SegmentedButton::new(&state.inner)
.height(Length::Units(32))
.style(crate::theme::SegmentedButton::Selection)
}

View file

@ -1,5 +1,49 @@
/// Copyright 2022 System76 <info@system76.com> // Copyright 2022 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
//! A widget providing a conjoined set of linear buttons for choosing between.
//!
//! ## Example
//!
//! Add the state and a message variant in your application for handling selections.
//!
//! ```no_run
//! use iced_core::Length;
//! use cosmic::theme;
//! use cosmic::widget::segmented_button;
//!
//! enum AppMessage {
//! Selected(segmented_button::Key)
//! }
//!
//! struct App {
//! ...
//! state: segmented_button::State<u16>(),
//! ...
//! }
//! ```
//!
//! Then add choices to the state, while activating the first.
//!
//! ```no_run
//! let first_key = application.state.insert("Choice A", 0);
//! application.state.insert("Choice B", 1);
//! application.state.insert("Choice C", 2);
//! application.state.activate(first_key);
//! ```
//!
//! Then use it in the view method to create segmented button widgets.
//!
//! ```no_run
//! let widget = segmentend_button(&application.state)
//! .style(theme::SegmentedButton::Selection)
//! .height(Length::Units(32))
//! .on_activate(AppMessage::Selected);
//! ```
/// COSMIC configurations of [`SegmentedButton`].
pub mod cosmic;
mod state; mod state;
mod style; mod style;
@ -22,19 +66,28 @@ struct PrivateWidgetState {
hovered: Key, hovered: Key,
} }
/// A linear set of options for choosing between. /// A widget providing a conjoined set of linear buttons for choosing between.
///
/// The data for the widget comes from a [`State`] that is maintained the application.
#[derive(Setters)] #[derive(Setters)]
pub struct SegmentedButton<'a, Message, Renderer> pub struct SegmentedButton<'a, Message, Renderer>
where where
Renderer: iced_native::Renderer, Renderer: iced_native::Renderer,
Renderer::Theme: StyleSheet, Renderer::Theme: StyleSheet,
{ {
/// Contains application state also used for drawing.
#[setters(skip)]
state: &'a WidgetState, state: &'a WidgetState,
/// The desired width of the widget.
width: Length, width: Length,
/// The desired height of the widget.
height: Length, height: Length,
/// The desired spacing between widgets.
spacing: u16, spacing: u16,
/// The style to draw the widget in.
#[setters(into)] #[setters(into)]
style: <Renderer::Theme as StyleSheet>::Style, style: <Renderer::Theme as StyleSheet>::Style,
/// Emits the ID of the activated widget on selection.
#[setters(skip)] #[setters(skip)]
on_activate: Option<Box<dyn Fn(Key) -> Message>>, on_activate: Option<Box<dyn Fn(Key) -> Message>>,
} }
@ -56,6 +109,7 @@ where
} }
} }
/// Emits the ID of the activated widget on selection.
#[must_use] #[must_use]
pub fn on_activate(mut self, on_activate: impl Fn(Key) -> Message + 'static) -> Self { pub fn on_activate(mut self, on_activate: impl Fn(Key) -> Message + 'static) -> Self {
self.on_activate = Some(Box::from(on_activate)); self.on_activate = Some(Box::from(on_activate));
@ -63,6 +117,7 @@ where
} }
} }
/// Creates a widget that presents multiple conjoined buttons.
#[must_use] #[must_use]
pub fn segmented_button<Message, Renderer, Data>( pub fn segmented_button<Message, Renderer, Data>(
state: &State<Data>, state: &State<Data>,

View file

@ -1,17 +1,20 @@
/// Copyright 2022 System76 <info@system76.com> // Copyright 2022 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use slotmap::{SecondaryMap, SlotMap}; use slotmap::{SecondaryMap, SlotMap};
use std::borrow::Cow; use std::borrow::Cow;
use crate::theme::Button;
slotmap::new_key_type! { slotmap::new_key_type! {
/// An ID for a segmented button
pub struct Key; pub struct Key;
} }
/// Contains all state for interacting with a [`SegmentedButton`]. /// Contains all state for interacting with a segmented button.
pub struct State<Data> { pub struct State<Data> {
/// State that is shared with widget drawing.
pub inner: WidgetState, pub inner: WidgetState,
/// State unique to the application.
pub data: SecondaryState<Data>, pub data: SecondaryState<Data>,
} }
@ -27,7 +30,10 @@ impl<Data> Default for State<Data> {
/// State which is most useful to the widget. /// State which is most useful to the widget.
#[derive(Default)] #[derive(Default)]
pub struct WidgetState { pub struct WidgetState {
/// The content used for drawing segmented buttons.
pub buttons: SlotMap<Key, ButtonContent>, pub buttons: SlotMap<Key, ButtonContent>,
/// The actively-selected segmented button.
pub active: Key, pub active: Key,
} }
@ -72,7 +78,7 @@ impl<Data> State<Data> {
} }
} }
/// Data to be drawn in a [`SegmentedButton`] button. /// Data to be drawn in a segmented button.
pub struct ButtonContent { pub struct ButtonContent {
pub text: Cow<'static, str>, pub text: Cow<'static, str>,
} }

View file

@ -1,8 +1,9 @@
/// Copyright 2022 System76 <info@system76.com> // Copyright 2022 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use iced_core::{Background, BorderRadius, Color}; use iced_core::{Background, BorderRadius, Color};
/// The appearance of a [`SegmentedButton`]. /// The appearance of a segmented button.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Appearance { pub struct Appearance {
pub background: Option<Background>, pub background: Option<Background>,
@ -14,7 +15,7 @@ pub struct Appearance {
pub button_hover: ButtonAppearance, pub button_hover: ButtonAppearance,
} }
/// The appearance of a button in the [`SegmentedButton`] /// The appearance of a button in the segmented button
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct ButtonAppearance { pub struct ButtonAppearance {
pub background: Option<Background>, pub background: Option<Background>,
@ -25,11 +26,11 @@ pub struct ButtonAppearance {
pub text_color: Color, pub text_color: Color,
} }
/// Defines the [`Appearance`] of a [`SegmentedButton`]. /// Defines the [`Appearance`] of a segmented button.
pub trait StyleSheet { pub trait StyleSheet {
/// The supported style of the [`StyleSheet`]. /// The supported style of the [`StyleSheet`].
type Style: Default; type Style: Default;
/// The [`Appearance`] of the [`SegmentedButton`]. /// The [`Appearance`] of the segmented button.
fn appearance(&self, style: &Self::Style) -> Appearance; fn appearance(&self, style: &Self::Style) -> Appearance;
} }