feat: MultiSelect support for segmented buttons
This commit is contained in:
parent
b1cbcfaf5b
commit
8988b25b6a
9 changed files with 263 additions and 112 deletions
|
|
@ -1,15 +1,20 @@
|
|||
// Copyright 2022 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{HorizontalSegmentedButton, SegmentedButton, State, VerticalSegmentedButton};
|
||||
use super::{
|
||||
state::Selectable, HorizontalSegmentedButton, SegmentedButton, State, VerticalSegmentedButton,
|
||||
};
|
||||
|
||||
/// 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 horizontal_view_switcher<Message, Data>(
|
||||
state: &State<Data>,
|
||||
) -> HorizontalSegmentedButton<Message, crate::Renderer> {
|
||||
pub fn horizontal_view_switcher<Selection, Message, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> HorizontalSegmentedButton<Selection, Message, crate::Renderer>
|
||||
where
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
.button_padding([16, 0, 16, 0])
|
||||
.button_height(48)
|
||||
|
|
@ -21,9 +26,12 @@ pub fn horizontal_view_switcher<Message, Data>(
|
|||
///
|
||||
/// The data for the widget comes from a [`State`] that is maintained the application.
|
||||
#[must_use]
|
||||
pub fn horizontal_segmented_selection<Message, Data>(
|
||||
state: &State<Data>,
|
||||
) -> HorizontalSegmentedButton<Message, crate::Renderer> {
|
||||
pub fn horizontal_segmented_selection<Selection, Message, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> HorizontalSegmentedButton<Selection, Message, crate::Renderer>
|
||||
where
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
.button_padding([16, 0, 16, 0])
|
||||
.button_height(32)
|
||||
|
|
@ -35,9 +43,12 @@ pub fn horizontal_segmented_selection<Message, Data>(
|
|||
///
|
||||
/// The data for the widget comes from a [`State`] that is maintained the application.
|
||||
#[must_use]
|
||||
pub fn vertical_segmented_selection<Message, Data>(
|
||||
state: &State<Data>,
|
||||
) -> VerticalSegmentedButton<Message, crate::Renderer> {
|
||||
pub fn vertical_segmented_selection<Selection, Message, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> VerticalSegmentedButton<Selection, Message, crate::Renderer>
|
||||
where
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
.button_padding([16, 0, 16, 0])
|
||||
.button_height(32)
|
||||
|
|
@ -49,9 +60,12 @@ pub fn vertical_segmented_selection<Message, Data>(
|
|||
///
|
||||
/// The data for the widget comes from a [`State`] that is maintained the application.
|
||||
#[must_use]
|
||||
pub fn vertical_view_switcher<Message, Data>(
|
||||
state: &State<Data>,
|
||||
) -> VerticalSegmentedButton<Message, crate::Renderer> {
|
||||
pub fn vertical_view_switcher<Selection, Message, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> VerticalSegmentedButton<Selection, Message, crate::Renderer>
|
||||
where
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
.button_padding([16, 0, 16, 0])
|
||||
.button_height(48)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2022 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::state::State;
|
||||
use super::state::{Selectable, State};
|
||||
use super::style::StyleSheet;
|
||||
use super::widget::{SegmentedButton, SegmentedVariant};
|
||||
|
||||
|
|
@ -12,31 +12,34 @@ use iced_native::layout;
|
|||
pub struct Horizontal;
|
||||
|
||||
/// Horizontal [`SegmentedButton`].
|
||||
pub type HorizontalSegmentedButton<'a, Message, Renderer> =
|
||||
SegmentedButton<'a, Horizontal, Message, Renderer>;
|
||||
pub type HorizontalSegmentedButton<'a, Selection, Message, Renderer> =
|
||||
SegmentedButton<'a, Horizontal, Selection, Message, Renderer>;
|
||||
|
||||
/// Horizontal implementation of the [`SegmentedButton`].
|
||||
#[must_use]
|
||||
pub fn horizontal_segmented_button<Message, Renderer, Data>(
|
||||
state: &State<Data>,
|
||||
) -> SegmentedButton<Horizontal, Message, Renderer>
|
||||
pub fn horizontal_segmented_button<Selection, Message, Renderer, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> SegmentedButton<Horizontal, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
+ iced_native::image::Renderer
|
||||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> SegmentedVariant for SegmentedButton<'a, Horizontal, Message, Renderer>
|
||||
impl<'a, Selection, Message, Renderer> SegmentedVariant
|
||||
for SegmentedButton<'a, Horizontal, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
+ iced_native::image::Renderer
|
||||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Selection: Selectable,
|
||||
{
|
||||
type Renderer = Renderer;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,13 +45,16 @@
|
|||
pub mod cosmic;
|
||||
|
||||
mod horizontal;
|
||||
|
||||
mod state;
|
||||
mod style;
|
||||
mod vertical;
|
||||
mod widget;
|
||||
|
||||
pub use self::horizontal::{horizontal_segmented_button, Horizontal, HorizontalSegmentedButton};
|
||||
pub use self::state::{Content, Key, SecondaryState, SharedWidgetState, State};
|
||||
pub use self::state::{
|
||||
Content, Key, MultiSelect, SecondaryState, Selectable, SharedWidgetState, SingleSelect, State,
|
||||
};
|
||||
pub use self::style::{Appearance, ButtonAppearance, ButtonStatusAppearance, StyleSheet};
|
||||
pub use self::vertical::{vertical_segmented_button, Vertical, VerticalSegmentedButton};
|
||||
pub use self::widget::{SegmentedButton, SegmentedVariant};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
use derive_setters::Setters;
|
||||
use slotmap::{SecondaryMap, SlotMap};
|
||||
use std::borrow::Cow;
|
||||
use std::{borrow::Cow, collections::HashSet};
|
||||
|
||||
use crate::widget::IconSource;
|
||||
|
||||
|
|
@ -13,15 +13,15 @@ slotmap::new_key_type! {
|
|||
}
|
||||
|
||||
/// Contains all state for interacting with a segmented button.
|
||||
pub struct State<Data> {
|
||||
pub struct State<Selection, Data> {
|
||||
/// State that is shared with widget drawing.
|
||||
pub inner: SharedWidgetState,
|
||||
pub inner: SharedWidgetState<Selection>,
|
||||
|
||||
/// State unique to the application.
|
||||
pub data: SecondaryState<Data>,
|
||||
}
|
||||
|
||||
impl<Data> Default for State<Data> {
|
||||
impl<Selection: Default, Data> Default for State<Selection, Data> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
inner: SharedWidgetState::default(),
|
||||
|
|
@ -32,43 +32,97 @@ impl<Data> Default for State<Data> {
|
|||
|
||||
/// State which is most useful to the widget.
|
||||
#[derive(Default)]
|
||||
pub struct SharedWidgetState {
|
||||
pub struct SharedWidgetState<Variant> {
|
||||
/// The content used for drawing segmented buttons.
|
||||
pub buttons: SlotMap<Key, Content>,
|
||||
|
||||
/// The actively-selected segmented button.
|
||||
pub active: Key,
|
||||
/// Manages selections
|
||||
pub selection: Variant,
|
||||
}
|
||||
|
||||
/// State which is most useful to the application.
|
||||
pub type SecondaryState<Data> = SecondaryMap<Key, Data>;
|
||||
|
||||
impl<Data> State<Data> {
|
||||
#[must_use]
|
||||
pub fn builder() -> Builder<Data> {
|
||||
Builder(Self::default())
|
||||
impl<Data> State<SingleSelect, Data> {
|
||||
pub fn activate(&mut self, key: Key) {
|
||||
self.inner.selection.activate(key);
|
||||
}
|
||||
|
||||
/// Activates this button.
|
||||
pub fn activate(&mut self, key: Key) {
|
||||
self.inner.active = key;
|
||||
pub fn deactivate(&mut self, key: Key) {
|
||||
self.inner.selection.deactivate(key);
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_active(&self, key: Key) -> bool {
|
||||
self.inner.selection.is_active(key)
|
||||
}
|
||||
|
||||
/// The ID of the active button.
|
||||
#[must_use]
|
||||
pub fn active(&self) -> Key {
|
||||
self.inner.active
|
||||
self.inner.selection.active
|
||||
}
|
||||
|
||||
/// Get the application data for the active button.
|
||||
#[must_use]
|
||||
pub fn active_data(&self) -> Option<&Data> {
|
||||
self.data(self.active())
|
||||
self.data.get(self.inner.selection.active)
|
||||
}
|
||||
|
||||
/// Mutable application data for the active button.
|
||||
#[must_use]
|
||||
pub fn active_data_mut(&mut self) -> Option<&mut Data> {
|
||||
self.data.get_mut(self.inner.selection.active)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Data> State<MultiSelect, Data> {
|
||||
pub fn activate(&mut self, key: Key) {
|
||||
if self.inner.selection.is_active(key) {
|
||||
self.inner.selection.deactivate(key);
|
||||
} else {
|
||||
self.inner.selection.activate(key);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deactivate(&mut self, key: Key) {
|
||||
self.inner.selection.deactivate(key);
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_active(&self, key: Key) -> bool {
|
||||
self.inner.selection.is_active(key)
|
||||
}
|
||||
|
||||
/// The IDs of the active buttons.
|
||||
pub fn active(&self) -> impl Iterator<Item = Key> + '_ {
|
||||
self.inner.selection.active.iter().copied()
|
||||
}
|
||||
|
||||
/// Get the application data for the active buttons.
|
||||
pub fn active_data(&self) -> impl Iterator<Item = (Key, &Data)> {
|
||||
self.inner.buttons.keys().filter_map(|key| {
|
||||
if self.inner.selection.is_active(key) {
|
||||
self.data.get(key).map(|data| (key, data))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// State which is most useful to the application.
|
||||
pub type SecondaryState<Data> = SecondaryMap<Key, Data>;
|
||||
|
||||
impl<Selection, Data> State<Selection, Data>
|
||||
where
|
||||
Selection: Selectable,
|
||||
{
|
||||
#[must_use]
|
||||
pub fn builder() -> Builder<Selection, Data> {
|
||||
Builder(Self::default())
|
||||
}
|
||||
|
||||
/// Convenience method for batching multiple operations
|
||||
#[must_use]
|
||||
pub fn batch(&mut self) -> Batch<Data> {
|
||||
pub fn batch(&mut self) -> Batch<Selection, Data> {
|
||||
Batch(self)
|
||||
}
|
||||
|
||||
|
|
@ -106,17 +160,104 @@ impl<Data> State<Data> {
|
|||
/// Inserts and activates a button.
|
||||
pub fn insert_active(&mut self, content: impl Into<Content>, data: Data) -> Key {
|
||||
let key = self.insert(content, data);
|
||||
self.activate(key);
|
||||
self.inner.selection.activate(key);
|
||||
key
|
||||
}
|
||||
|
||||
/// Removes a button.
|
||||
pub fn remove(&mut self, key: Key) -> Option<Data> {
|
||||
self.inner.buttons.remove(key);
|
||||
self.inner.selection.deactivate(key);
|
||||
self.data.remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Selectable: Default {
|
||||
fn activate(&mut self, key: Key);
|
||||
|
||||
fn deactivate(&mut self, key: Key);
|
||||
|
||||
fn is_active(&self, key: Key) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SingleSelect {
|
||||
pub active: Key,
|
||||
}
|
||||
|
||||
impl Selectable for SingleSelect {
|
||||
fn activate(&mut self, key: Key) {
|
||||
self.active = key;
|
||||
}
|
||||
|
||||
fn deactivate(&mut self, _key: Key) {
|
||||
self.active = Key::default();
|
||||
}
|
||||
|
||||
fn is_active(&self, key: Key) -> bool {
|
||||
self.active == key
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MultiSelect {
|
||||
pub active: HashSet<Key>,
|
||||
}
|
||||
|
||||
impl Selectable for MultiSelect {
|
||||
fn activate(&mut self, key: Key) {
|
||||
self.active.insert(key);
|
||||
}
|
||||
|
||||
fn deactivate(&mut self, key: Key) {
|
||||
self.active.remove(&key);
|
||||
}
|
||||
|
||||
fn is_active(&self, key: Key) -> bool {
|
||||
self.active.contains(&key)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder<Selection, Data>(State<Selection, Data>);
|
||||
|
||||
impl<Selection: Selectable, Data> Builder<Selection, Data> {
|
||||
pub fn insert(mut self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_active(mut self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert_active(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> State<Selection, Data> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience type for batching multiple operations
|
||||
pub struct Batch<'a, Selection, Data>(&'a mut State<Selection, Data>);
|
||||
|
||||
impl<'a, Selection: Selectable, Data> Batch<'a, Selection, Data> {
|
||||
/// Insert a new button.
|
||||
pub fn insert(self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Inserts and activates a button.
|
||||
pub fn insert_active(self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert_active(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Removes a button.
|
||||
pub fn remove(&mut self, key: Key) {
|
||||
self.0.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Data to be drawn in a segmented button.
|
||||
#[derive(Default, Setters)]
|
||||
pub struct Content {
|
||||
|
|
@ -149,43 +290,3 @@ impl From<Cow<'static, str>> for Content {
|
|||
Content::default().text(text)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder<Data>(State<Data>);
|
||||
|
||||
impl<Data> Builder<Data> {
|
||||
pub fn insert(mut self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_active(mut self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert_active(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> State<Data> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience type for batching multiple operations
|
||||
pub struct Batch<'a, Data>(&'a mut State<Data>);
|
||||
|
||||
impl<'a, Data> Batch<'a, Data> {
|
||||
/// Insert a new button.
|
||||
pub fn insert(self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Inserts and activates a button.
|
||||
pub fn insert_active(self, content: impl Into<Content>, data: Data) -> Self {
|
||||
self.0.insert_active(content, data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Removes a button.
|
||||
pub fn remove(&mut self, key: Key) {
|
||||
self.0.remove(key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2022 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::state::State;
|
||||
use super::state::{Selectable, State};
|
||||
use super::style::StyleSheet;
|
||||
use super::widget::{SegmentedButton, SegmentedVariant};
|
||||
|
||||
|
|
@ -12,31 +12,34 @@ use iced_native::layout;
|
|||
pub struct Vertical;
|
||||
|
||||
/// Vertical [`SegmentedButton`].
|
||||
pub type VerticalSegmentedButton<'a, Message, Renderer> =
|
||||
SegmentedButton<'a, Vertical, Message, Renderer>;
|
||||
pub type VerticalSegmentedButton<'a, Selection, Message, Renderer> =
|
||||
SegmentedButton<'a, Vertical, Selection, Message, Renderer>;
|
||||
|
||||
/// Vertical implementation of the [`SegmentedButton`].
|
||||
#[must_use]
|
||||
pub fn vertical_segmented_button<Message, Renderer, Data>(
|
||||
state: &State<Data>,
|
||||
) -> SegmentedButton<Vertical, Message, Renderer>
|
||||
pub fn vertical_segmented_button<Selection, Message, Renderer, Data>(
|
||||
state: &State<Selection, Data>,
|
||||
) -> SegmentedButton<Vertical, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
+ iced_native::image::Renderer
|
||||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Selection: Selectable,
|
||||
{
|
||||
SegmentedButton::new(&state.inner)
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> SegmentedVariant for SegmentedButton<'a, Vertical, Message, Renderer>
|
||||
impl<'a, Selection, Message, Renderer> SegmentedVariant
|
||||
for SegmentedButton<'a, Vertical, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
+ iced_native::image::Renderer
|
||||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Selection: Selectable,
|
||||
{
|
||||
type Renderer = Renderer;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use super::state::{Key, SharedWidgetState};
|
||||
use super::state::{Key, Selectable, SharedWidgetState};
|
||||
use super::style::StyleSheet;
|
||||
|
||||
use derive_setters::Setters;
|
||||
|
|
@ -35,17 +35,18 @@ pub trait SegmentedVariant {
|
|||
}
|
||||
|
||||
#[derive(Setters)]
|
||||
pub struct SegmentedButton<'a, Variant, Message, Renderer>
|
||||
pub struct SegmentedButton<'a, Variant, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
+ iced_native::image::Renderer
|
||||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Selection: Selectable,
|
||||
{
|
||||
/// Contains application state also used for drawing.
|
||||
#[setters(skip)]
|
||||
pub(super) state: &'a SharedWidgetState,
|
||||
pub(super) state: &'a SharedWidgetState<Selection>,
|
||||
/// Padding around a button.
|
||||
pub(super) button_padding: [u16; 4],
|
||||
/// Desired height of a button.
|
||||
|
|
@ -77,7 +78,8 @@ where
|
|||
variant: PhantomData<Variant>,
|
||||
}
|
||||
|
||||
impl<'a, Variant, Message, Renderer> SegmentedButton<'a, Variant, Message, Renderer>
|
||||
impl<'a, Variant, Selection, Message, Renderer>
|
||||
SegmentedButton<'a, Variant, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
|
|
@ -85,9 +87,10 @@ where
|
|||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Self: SegmentedVariant<Renderer = Renderer>,
|
||||
Selection: Selectable,
|
||||
{
|
||||
#[must_use]
|
||||
pub fn new(state: &'a SharedWidgetState) -> Self {
|
||||
pub fn new(state: &'a SharedWidgetState<Selection>) -> Self {
|
||||
Self {
|
||||
state,
|
||||
button_padding: [4, 4, 4, 4],
|
||||
|
|
@ -153,8 +156,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Variant, Message, Renderer> Widget<Message, Renderer>
|
||||
for SegmentedButton<'a, Variant, Message, Renderer>
|
||||
impl<'a, Variant, Selection, Message, Renderer> Widget<Message, Renderer>
|
||||
for SegmentedButton<'a, Variant, Selection, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
+ iced_native::text::Renderer
|
||||
|
|
@ -162,6 +165,7 @@ where
|
|||
+ iced_native::svg::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
Self: SegmentedVariant<Renderer = Renderer>,
|
||||
Selection: Selectable,
|
||||
Message: 'static + Clone,
|
||||
{
|
||||
fn tag(&self) -> tree::Tag {
|
||||
|
|
@ -273,7 +277,7 @@ where
|
|||
for (nth, (key, content)) in self.state.buttons.iter().enumerate() {
|
||||
let mut bounds = self.variant_button_bounds(bounds, nth);
|
||||
|
||||
let (status_appearance, font) = if self.state.active == key {
|
||||
let (status_appearance, font) = if self.state.selection.is_active(key) {
|
||||
(appearance.active, &self.font_active)
|
||||
} else if state.hovered == key {
|
||||
(appearance.hover, &self.font_hovered)
|
||||
|
|
@ -392,7 +396,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Variant, Message, Renderer> From<SegmentedButton<'a, Variant, Message, Renderer>>
|
||||
impl<'a, Variant, Selection, Message, Renderer>
|
||||
From<SegmentedButton<'a, Variant, Selection, Message, Renderer>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: iced_native::Renderer
|
||||
|
|
@ -401,11 +406,13 @@ where
|
|||
+ iced_native::svg::Renderer
|
||||
+ 'a,
|
||||
Renderer::Theme: StyleSheet,
|
||||
SegmentedButton<'a, Variant, Message, Renderer>: SegmentedVariant<Renderer = Renderer>,
|
||||
SegmentedButton<'a, Variant, Selection, Message, Renderer>:
|
||||
SegmentedVariant<Renderer = Renderer>,
|
||||
Variant: 'static,
|
||||
Selection: Selectable,
|
||||
Message: 'static + Clone,
|
||||
{
|
||||
fn from(mut widget: SegmentedButton<'a, Variant, Message, Renderer>) -> Self {
|
||||
fn from(mut widget: SegmentedButton<'a, Variant, Selection, Message, Renderer>) -> Self {
|
||||
if widget.state.buttons.is_empty() {
|
||||
widget.spacing = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue