diff --git a/src/app/mod.rs b/src/app/mod.rs index 93a91a702a7..64aafbd8d20 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -478,7 +478,7 @@ where } /// Allows COSMIC to integrate with your application's [`nav_bar::Model`]. - fn nav_model(&self) -> Option<&nav_bar::Model> { + fn nav_model(&self) -> Option<&nav_bar::Model>> { None } diff --git a/src/widget/color_picker/mod.rs b/src/widget/color_picker/mod.rs index 7ff646b87fb..f3366b3ba41 100644 --- a/src/widget/color_picker/mod.rs +++ b/src/widget/color_picker/mod.rs @@ -62,9 +62,9 @@ pub enum ColorPickerUpdate { } #[derive(Setters)] -pub struct ColorPickerModel { +pub struct ColorPickerModel { #[setters(skip)] - segmented_model: Model, + segmented_model: Model, #[setters(skip)] active_color: palette::Hsv, #[setters(skip)] @@ -86,7 +86,7 @@ pub struct ColorPickerModel { copied_at: Option, } -impl ColorPickerModel { +impl ColorPickerModel { #[must_use] pub fn new( hex: impl Into> + Clone, @@ -118,11 +118,11 @@ impl ColorPickerModel { /// Get a color picker button that displays the applied color /// - pub fn picker_button<'a, Message: 'static, T: Fn(ColorPickerUpdate) -> Message>( + pub fn picker_button<'a, T: Fn(ColorPickerUpdate) -> Message>( &self, f: T, icon_portion: Option, - ) -> crate::widget::Button<'a, Message, crate::Theme, crate::Renderer> { + ) -> crate::widget::Button<'a, Message, crate::Theme, crate::Renderer> where Message: 'static { color_button( Some(f(ColorPickerUpdate::ToggleColorPicker)), self.applied_color, @@ -130,7 +130,7 @@ impl ColorPickerModel { ) } - pub fn update(&mut self, update: ColorPickerUpdate) -> Command { + pub fn update(&mut self, update: ColorPickerUpdate) -> Command { match update { ColorPickerUpdate::ActiveColor(c) => { self.must_clear_cache.store(true, Ordering::SeqCst); @@ -222,7 +222,7 @@ impl ColorPickerModel { } #[must_use] - pub fn builder( + pub fn builder( &self, on_update: fn(ColorPickerUpdate) -> Message, ) -> ColorPickerBuilder { @@ -246,7 +246,7 @@ impl ColorPickerModel { #[derive(Setters, Clone)] pub struct ColorPickerBuilder<'a, Message> { #[setters(skip)] - model: &'a Model, + model: &'a Model, #[setters(skip)] active_color: palette::Hsv, #[setters(skip)] diff --git a/src/widget/nav_bar.rs b/src/widget/nav_bar.rs index 764f8050f41..27a72403da5 100644 --- a/src/widget/nav_bar.rs +++ b/src/widget/nav_bar.rs @@ -18,13 +18,13 @@ use crate::{theme, Theme}; use super::dnd_destination::DragId; pub type Id = segmented_button::Entity; -pub type Model = segmented_button::SingleSelectModel; +pub type Model = segmented_button::SingleSelectModel; /// Navigation side panel for switching between views. /// /// For details on the model, see the [`segmented_button`] module for more details. pub fn nav_bar( - model: &segmented_button::SingleSelectModel, + model: &Model, on_activate: fn(segmented_button::Entity) -> Message, ) -> NavBar { NavBar { @@ -35,7 +35,7 @@ pub fn nav_bar( /// Navigation side panel for switching between views. /// Can receive drag and drop events. pub fn nav_bar_dnd( - model: &segmented_button::SingleSelectModel, + model: &Model, on_activate: fn(segmented_button::Entity) -> Message, on_dnd_enter: impl Fn(segmented_button::Entity, Vec) -> Message + 'static, on_dnd_leave: impl Fn(segmented_button::Entity) -> Message + 'static, diff --git a/src/widget/segmented_button/horizontal.rs b/src/widget/segmented_button/horizontal.rs index 36decb28b49..e2c838a4d11 100644 --- a/src/widget/segmented_button/horizontal.rs +++ b/src/widget/segmented_button/horizontal.rs @@ -22,10 +22,10 @@ pub struct Horizontal; /// /// For details on the model, see the [`segmented_button`](super) module for more details. pub fn horizontal( - model: &Model, + model: &Model, ) -> SegmentedButton where - Model: Selectable, + Model: Selectable, { SegmentedButton::new(model) } @@ -33,7 +33,7 @@ where impl<'a, SelectionMode, Message> SegmentedVariant for SegmentedButton<'a, Horizontal, SelectionMode, Message> where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { fn variant_appearance( diff --git a/src/widget/segmented_button/model/builder.rs b/src/widget/segmented_button/model/builder.rs index 87d25adba25..00085c8ab56 100644 --- a/src/widget/segmented_button/model/builder.rs +++ b/src/widget/segmented_button/model/builder.rs @@ -8,38 +8,44 @@ use crate::widget::icon::Icon; use std::borrow::Cow; /// A builder for a [`Model`]. -#[derive(Default)] -pub struct ModelBuilder(Model); +pub struct ModelBuilder(Model); + +//TODO: Default derive ends up requiring Message to implement Default +impl Default for ModelBuilder { + fn default() -> Self { + Self(Model::default()) + } +} /// Constructs a new item for the [`ModelBuilder`]. -pub struct BuilderEntity { - model: ModelBuilder, +pub struct BuilderEntity { + model: ModelBuilder, id: Entity, } -impl ModelBuilder +impl ModelBuilder where - Model: Selectable, + Model: Selectable, { /// Inserts a new item and its associated data into the model. #[must_use] pub fn insert( mut self, - builder: impl Fn(BuilderEntity) -> BuilderEntity, + builder: impl Fn(BuilderEntity) -> BuilderEntity, ) -> Self { let id = self.0.insert().id(); builder(BuilderEntity { model: self, id }).model } /// Consumes the builder and returns the model. - pub fn build(self) -> Model { + pub fn build(self) -> Model { self.0 } } -impl BuilderEntity +impl BuilderEntity where - Model: Selectable, + Model: Selectable, { /// Activates the newly-inserted item. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] diff --git a/src/widget/segmented_button/model/entity.rs b/src/widget/segmented_button/model/entity.rs index c9f0997dbb9..0a9ba2e66df 100644 --- a/src/widget/segmented_button/model/entity.rs +++ b/src/widget/segmented_button/model/entity.rs @@ -10,14 +10,14 @@ use crate::widget::Icon; use super::{Entity, Model, Selectable}; /// A newly-inserted item which may have additional actions applied to it. -pub struct EntityMut<'a, SelectionMode: Default> { +pub struct EntityMut<'a, SelectionMode: Default, Message> { pub(super) id: Entity, - pub(super) model: &'a mut Model, + pub(super) model: &'a mut Model, } -impl<'a, SelectionMode: Default> EntityMut<'a, SelectionMode> +impl<'a, SelectionMode: Default, Message> EntityMut<'a, SelectionMode, Message> where - Model: Selectable, + Model: Selectable, { /// Activates the newly-inserted item. /// diff --git a/src/widget/segmented_button/model/mod.rs b/src/widget/segmented_button/model/mod.rs index 49003239c31..b743e76bbd6 100644 --- a/src/widget/segmented_button/model/mod.rs +++ b/src/widget/segmented_button/model/mod.rs @@ -10,7 +10,7 @@ pub use self::entity::EntityMut; mod selection; pub use self::selection::{MultiSelect, Selectable, SingleSelect}; -use crate::widget::Icon; +use crate::{Element, widget::Icon}; use slotmap::{SecondaryMap, SlotMap}; use std::any::{Any, TypeId}; use std::borrow::Cow; @@ -37,27 +37,29 @@ impl Default for Settings { } /// A model for single-select button selection. -pub type SingleSelectModel = Model; +pub type SingleSelectModel = Model; /// Single-select variant of an [`EntityMut`]. -pub type SingleSelectEntityMut<'a> = EntityMut<'a, SingleSelect>; +pub type SingleSelectEntityMut<'a, Message> = EntityMut<'a, SingleSelect, Message>; /// A model for multi-select button selection. -pub type MultiSelectModel = Model; +pub type MultiSelectModel = Model; /// Multi-select variant of an [`EntityMut`]. -pub type MultiSelectEntityMut<'a> = EntityMut<'a, MultiSelect>; +pub type MultiSelectEntityMut<'a, Message> = EntityMut<'a, MultiSelect, Message>; /// The portion of the model used only by the application. #[derive(Debug, Default)] pub(super) struct Storage(HashMap>>); /// The model held by the application, containing the unique IDs and data of each inserted item. -#[derive(Default)] -pub struct Model { +pub struct Model { /// The content used for drawing segmented items. pub(super) items: SlotMap, + /// Elements optionally-defined for each item. + pub(super) elements: SecondaryMap>, + /// Icons optionally-defined for each item. pub(super) icons: SecondaryMap, @@ -77,7 +79,23 @@ pub struct Model { pub(super) storage: Storage, } -impl Model +//TODO: Default derive ends up requiring Message to implement Default +impl Default for Model { + fn default() -> Self { + Self { + items: SlotMap::default(), + elements: SecondaryMap::default(), + icons: SecondaryMap::default(), + indents: SecondaryMap::default(), + text: SecondaryMap::default(), + order: VecDeque::default(), + selection: SelectionMode::default(), + storage: Storage::default(), + } + } +} + +impl Model where Self: Selectable, { @@ -110,7 +128,7 @@ where /// .build(); /// ``` #[must_use] - pub fn builder() -> ModelBuilder { + pub fn builder() -> ModelBuilder { ModelBuilder::default() } @@ -259,7 +277,7 @@ where /// let id = model.insert().text("Item A").icon("custom-icon").id(); /// ``` #[must_use] - pub fn insert(&mut self) -> EntityMut { + pub fn insert(&mut self) -> EntityMut { let id = self.items.insert(Settings::default()); self.order.push_back(id); EntityMut { model: self, id } diff --git a/src/widget/segmented_button/model/selection.rs b/src/widget/segmented_button/model/selection.rs index 1366c18ceea..1b10b851ba9 100644 --- a/src/widget/segmented_button/model/selection.rs +++ b/src/widget/segmented_button/model/selection.rs @@ -24,7 +24,7 @@ pub struct SingleSelect { pub active: Entity, } -impl Selectable for Model { +impl Selectable for Model { fn activate(&mut self, id: Entity) { if !self.items.contains_key(id) { return; @@ -44,7 +44,7 @@ impl Selectable for Model { } } -impl Model { +impl Model { /// Get an immutable reference to the data associated with the active item. #[must_use] pub fn active_data(&self) -> Option<&Data> { @@ -75,7 +75,7 @@ pub struct MultiSelect { pub active: HashSet, } -impl Selectable for Model { +impl Selectable for Model { fn activate(&mut self, id: Entity) { if !self.items.contains_key(id) { return; @@ -95,7 +95,7 @@ impl Selectable for Model { } } -impl Model { +impl Model { /// Deactivates the item in the model. pub fn deactivate(&mut self, id: Entity) { Selectable::deactivate(self, id); diff --git a/src/widget/segmented_button/vertical.rs b/src/widget/segmented_button/vertical.rs index 5b5d9ace972..dc7cd015295 100644 --- a/src/widget/segmented_button/vertical.rs +++ b/src/widget/segmented_button/vertical.rs @@ -21,10 +21,10 @@ pub type VerticalSegmentedButton<'a, SelectionMode, Message> = /// /// For details on the model, see the [`segmented_button`](super) module for more details. pub fn vertical( - model: &Model, + model: &Model, ) -> SegmentedButton where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { SegmentedButton::new(model) @@ -33,7 +33,7 @@ where impl<'a, SelectionMode, Message> SegmentedVariant for SegmentedButton<'a, Vertical, SelectionMode, Message> where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { fn variant_appearance( diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 73f7b365095..0560f93f362 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -71,12 +71,12 @@ pub trait SegmentedVariant { #[must_use] pub struct SegmentedButton<'a, Variant, SelectionMode, Message> where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { /// The model borrowed from the application create this widget. #[setters(skip)] - pub(super) model: &'a Model, + pub(super) model: &'a Model, /// iced widget ID pub(super) id: Id, /// The icon used for the close button. @@ -151,10 +151,10 @@ where impl<'a, Variant, SelectionMode, Message> SegmentedButton<'a, Variant, SelectionMode, Message> where Self: SegmentedVariant, - Model: Selectable, + Model: Selectable, SelectionMode: Default, { - pub fn new(model: &'a Model) -> Self { + pub fn new(model: &'a Model) -> Self { Self { model, id: Id::unique(), @@ -536,7 +536,7 @@ impl<'a, Variant, SelectionMode, Message> Widget where Self: SegmentedVariant, - Model: Selectable, + Model: Selectable, SelectionMode: Default, Message: 'static + Clone, { @@ -1555,7 +1555,7 @@ impl<'a, Variant, SelectionMode, Message> From: SegmentedVariant, Variant: 'static, - Model: Selectable, + Model: Selectable, SelectionMode: Default, Message: 'static + Clone, { diff --git a/src/widget/segmented_control.rs b/src/widget/segmented_control.rs index 7ba7a40bad4..2aa6ec20848 100644 --- a/src/widget/segmented_control.rs +++ b/src/widget/segmented_control.rs @@ -15,10 +15,10 @@ use super::segmented_button::{ /// /// For details on the model, see the [`segmented_button`] module for more details. pub fn horizontal( - model: &Model, + model: &Model, ) -> HorizontalSegmentedButton where - Model: Selectable, + Model: Selectable, { let theme = crate::theme::active(); let space_s = theme.cosmic().space_s(); @@ -40,10 +40,10 @@ where /// /// For details on the model, see the [`segmented_button`] module for more details. pub fn vertical( - model: &Model, + model: &Model, ) -> VerticalSegmentedButton where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { let theme = crate::theme::active(); diff --git a/src/widget/tab_bar.rs b/src/widget/tab_bar.rs index bcbb14d76cf..807b58b8a13 100644 --- a/src/widget/tab_bar.rs +++ b/src/widget/tab_bar.rs @@ -15,10 +15,10 @@ use super::segmented_button::{ /// /// For details on the model, see the [`segmented_button`] module for more details. pub fn horizontal( - model: &Model, + model: &Model, ) -> HorizontalSegmentedButton where - Model: Selectable, + Model: Selectable, { let theme = crate::theme::active(); let space_s = theme.cosmic().space_s(); @@ -38,10 +38,10 @@ where /// The data for the widget comes from a model that is maintained the application. /// For details on the model, see the [`segmented_button`] module for more details. pub fn vertical( - model: &Model, + model: &Model, ) -> VerticalSegmentedButton where - Model: Selectable, + Model: Selectable, SelectionMode: Default, { let theme = crate::theme::active();