From fdf3369cea2f772aabb5f7c4e5cdf6406780f6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vuka=C5=A1in=20Vojinovi=C4=87?= <150025636+git-f0x@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:24:53 +0200 Subject: [PATCH] chore: re-export iced row and column This removes the custom row and column implementations and uses the iced ones directly. --- examples/about/src/main.rs | 2 +- examples/application/src/main.rs | 4 +- examples/calendar/src/main.rs | 6 +-- examples/image-button/src/main.rs | 2 +- examples/subscriptions/src/main.rs | 2 +- examples/text-input/src/main.rs | 4 +- src/ext.rs | 66 ------------------------ src/widget/about.rs | 56 +++++++++++--------- src/widget/button/icon.rs | 7 +-- src/widget/calendar.rs | 2 +- src/widget/context_menu.rs | 2 +- src/widget/header_bar.rs | 74 ++++++++++++--------------- src/widget/list/column.rs | 2 +- src/widget/mod.rs | 65 +++-------------------- src/widget/segmented_button/widget.rs | 6 +-- src/widget/settings/item.rs | 12 ++--- src/widget/settings/mod.rs | 4 +- src/widget/table/widget/compact.rs | 6 +-- src/widget/table/widget/standard.rs | 4 +- src/widget/toaster/mod.rs | 4 +- 20 files changed, 103 insertions(+), 227 deletions(-) diff --git a/examples/about/src/main.rs b/examples/about/src/main.rs index 50f25da4..c25a9b9a 100644 --- a/examples/about/src/main.rs +++ b/examples/about/src/main.rs @@ -132,7 +132,7 @@ impl cosmic::Application for App { fn view(&self) -> Element<'_, Self::Message> { let show_about_button = widget::button::text("Show about").on_press(Message::ToggleAbout); let centered = cosmic::widget::container( - widget::column() + widget::column::with_capacity(1) .push(show_about_button) .width(Length::Fill) .height(Length::Shrink) diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index 831a47f1..53f1c28e 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -54,7 +54,7 @@ impl widget::menu::Action for Action { /// Runs application with these settings #[rustfmt::skip] fn main() -> Result<(), Box> { - + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); @@ -190,7 +190,7 @@ impl cosmic::Application for App { .map_or("No page selected", String::as_str); let centered = widget::container( - widget::column() + widget::column::with_capacity(5) .push(widget::text::body(page_content)) .push( widget::text_input::text_input("", &self.input_1) diff --git a/examples/calendar/src/main.rs b/examples/calendar/src/main.rs index 240684c6..494087d1 100644 --- a/examples/calendar/src/main.rs +++ b/examples/calendar/src/main.rs @@ -85,8 +85,6 @@ impl cosmic::Application for App { /// Creates a view after each update. fn view(&self) -> Element<'_, Self::Message> { - let mut content = cosmic::widget::column().spacing(12); - let calendar = cosmic::widget::calendar( &self.calendar_model, |date| Message::DateSelected(date), @@ -95,9 +93,7 @@ impl cosmic::Application for App { Weekday::Sunday, ); - content = content.push(calendar); - - let centered = cosmic::widget::container(content) + let centered = cosmic::widget::container(calendar) .width(iced::Length::Fill) .height(iced::Length::Shrink) .align_x(iced::Alignment::Center) diff --git a/examples/image-button/src/main.rs b/examples/image-button/src/main.rs index 0ac906ca..c68c7070 100644 --- a/examples/image-button/src/main.rs +++ b/examples/image-button/src/main.rs @@ -80,7 +80,7 @@ impl cosmic::Application for App { /// Creates a view after each update. fn view(&self) -> Element<'_, Self::Message> { - let mut content = cosmic::widget::column().spacing(12); + let mut content = cosmic::widget::column::with_capacity(self.images.len()).spacing(12); for (id, image) in self.images.iter().enumerate() { content = content.push( diff --git a/examples/subscriptions/src/main.rs b/examples/subscriptions/src/main.rs index 47bd3772..17e630aa 100644 --- a/examples/subscriptions/src/main.rs +++ b/examples/subscriptions/src/main.rs @@ -64,7 +64,7 @@ impl cosmic::Application for App { /// Creates a view after each update. fn view(&self) -> Element<'_, Self::Message> { - widget::row().into() + widget::Row::new().into() } } diff --git a/examples/text-input/src/main.rs b/examples/text-input/src/main.rs index ea99666c..c17fcd5c 100644 --- a/examples/text-input/src/main.rs +++ b/examples/text-input/src/main.rs @@ -99,7 +99,9 @@ impl cosmic::Application for App { let inline = cosmic::widget::inline_input("", &self.input).on_input(Message::Input); - let column = cosmic::widget::column().push(editable).push(inline); + let column = cosmic::widget::column::with_capacity(2) + .push(editable) + .push(inline); let centered = cosmic::widget::container(column.width(200)) .width(iced::Length::Fill) diff --git a/src/ext.rs b/src/ext.rs index c85e6e86..8eb749e5 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -19,72 +19,6 @@ impl ElementExt for crate::Element<'_, Message> { } } -/// Additional methods for the [`Column`] and [`Row`] widgets. -pub trait CollectionWidget<'a, Message: 'a>: - Widget -where - Self: Sized, -{ - /// Moves all the elements of `other` into `self`, leaving `other` empty. - #[must_use] - fn append(self, other: &mut Vec) -> Self - where - E: Into>; - - /// Appends all elements in an iterator to the widget. - #[must_use] - fn extend(mut self, iterator: impl Iterator) -> Self - where - E: Into>, - { - for item in iterator { - self = self.push(item.into()); - } - - self - } - - /// Pushes an element into the widget. - #[must_use] - fn push(self, element: impl Into>) -> Self; - - /// Conditionally pushes an element to the widget. - #[must_use] - fn push_maybe(self, element: Option>>) -> Self { - if let Some(element) = element { - self.push(element.into()) - } else { - self - } - } -} - -impl<'a, Message: 'a> CollectionWidget<'a, Message> for crate::widget::Column<'a, Message> { - fn append(self, other: &mut Vec) -> Self - where - E: Into>, - { - self.extend(other.drain(..).map(Into::into)) - } - - fn push(self, element: impl Into>) -> Self { - self.push(element) - } -} - -impl<'a, Message: 'a> CollectionWidget<'a, Message> for crate::widget::Row<'a, Message> { - fn append(self, other: &mut Vec) -> Self - where - E: Into>, - { - self.extend(other.drain(..).map(Into::into)) - } - - fn push(self, element: impl Into>) -> Self { - self.push(element) - } -} - pub trait ColorExt { /// Combines color with background to create appearance of transparency. #[must_use] diff --git a/src/widget/about.rs b/src/widget/about.rs index ba88e03a..148af02a 100644 --- a/src/widget/about.rs +++ b/src/widget/about.rs @@ -47,32 +47,40 @@ pub struct About { fn add_contributors(contributors: Vec<(&str, &str)>) -> Vec<(String, String)> { contributors .into_iter() - .map(|(name, email)| (name.to_string(), format!("mailto:{email}"))) + .map(|(name, email)| (name.into(), format!("mailto:{email}"))) .collect() } -macro_rules! set_contributors { - ($field:ident, $doc:expr) => { - #[doc = $doc] - pub fn $field(mut self, contributors: impl Into>) -> Self { - self.$field = add_contributors(contributors.into()); - self - } - }; -} - impl<'a> About { - set_contributors!(artists, "Artists who contributed to the application."); - set_contributors!(designers, "Designers who contributed to the application."); - set_contributors!(developers, "Developers who contributed to the application."); - set_contributors!( - documenters, - "Documenters who contributed to the application." - ); - set_contributors!( - translators, - "Translators who contributed to the application." - ); + /// Artists who contributed to the application. + pub fn artists(mut self, contributors: impl Into>) -> Self { + self.artists = add_contributors(contributors.into()); + self + } + + /// Designers who contributed to the application. + pub fn designers(mut self, contributors: impl Into>) -> Self { + self.designers = add_contributors(contributors.into()); + self + } + + /// Developers who contributed to the application. + pub fn developers(mut self, contributors: impl Into>) -> Self { + self.developers = add_contributors(contributors.into()); + self + } + + /// Documenters who contributed to the application. + pub fn documenters(mut self, contributors: impl Into>) -> Self { + self.documenters = add_contributors(contributors.into()); + self + } + + /// Translators who contributed to the application. + pub fn translators(mut self, contributors: impl Into>) -> Self { + self.translators = add_contributors(contributors.into()); + self + } /// Links associated with the application. pub fn links, V: Into>( @@ -97,7 +105,7 @@ pub fn about<'a, Message: Clone + 'static>( } = crate::theme::spacing(); let section_button = |name: &'a str, url: &'a str| -> Element<'a, Message> { - widget::row() + widget::row::with_capacity(3) .push(widget::text(name)) .push(space::horizontal()) .push_maybe( @@ -158,7 +166,7 @@ pub fn about<'a, Message: Clone + 'static>( let copyright = about.copyright.as_ref().map(widget::text::body); let comments = about.comments.as_ref().map(widget::text::body); - widget::column() + widget::column::with_capacity(10) .push_maybe(header) .push_maybe(links_section) .push_maybe(developers_section) diff --git a/src/widget/button/icon.rs b/src/widget/button/icon.rs index edb54272..04d2bdd5 100644 --- a/src/widget/button/icon.rs +++ b/src/widget/button/icon.rs @@ -3,10 +3,7 @@ use super::{Builder, ButtonClass}; use crate::Element; -use crate::widget::{ - icon::{self, Handle}, - tooltip, -}; +use crate::widget::{icon::Handle, tooltip}; use apply::Apply; use iced_core::{Alignment, Length, Padding, font::Weight, text::LineHeight, widget::Id}; use std::borrow::Cow; @@ -133,7 +130,7 @@ impl Button<'_, Message> { } impl<'a, Message: Clone + 'static> From> for Element<'a, Message> { - fn from(mut builder: Button<'a, Message>) -> Element<'a, Message> { + fn from(builder: Button<'a, Message>) -> Element<'a, Message> { let mut content = Vec::with_capacity(2); content.push( diff --git a/src/widget/calendar.rs b/src/widget/calendar.rs index 7c09d39c..19758472 100644 --- a/src/widget/calendar.rs +++ b/src/widget/calendar.rs @@ -212,7 +212,7 @@ where let content_list = column::with_children([ row::with_children([ - column().push(date).push(day).into(), + column([date.into(), day.into()]).into(), crate::widget::space::horizontal() .width(Length::Fill) .into(), diff --git a/src/widget/context_menu.rs b/src/widget/context_menu.rs index 918d4da2..3f35f04a 100644 --- a/src/widget/context_menu.rs +++ b/src/widget/context_menu.rs @@ -32,7 +32,7 @@ pub fn context_menu<'a, Message: 'static + Clone>( content: content.into(), context_menu: context_menu.map(|menus| { vec![menu::Tree::with_children( - crate::Element::from(crate::widget::row::<'static, Message>()), + crate::Element::from(crate::widget::Row::new()), menus, )] }), diff --git a/src/widget/header_bar.rs b/src/widget/header_bar.rs index 1c0ca2c0..a772f7d2 100644 --- a/src/widget/header_bar.rs +++ b/src/widget/header_bar.rs @@ -243,10 +243,13 @@ impl<'a, Message: Clone + 'static> Widget Widget, viewport: &iced_core::Rectangle, ) { - for ((e, s), l) in self - .elems_mut() + self.elems_mut() .zip(&mut state.children) .zip(layout.children()) - { - e.as_widget_mut() - .update(s, event, l, cursor, renderer, clipboard, shell, viewport); - } + .for_each(|((e, s), l)| { + e.as_widget_mut() + .update(s, event, l, cursor, renderer, clipboard, shell, viewport); + }); } fn mouse_interaction( @@ -296,13 +298,12 @@ impl<'a, Message: Clone + 'static> Widget, ) { - for ((e, s), l) in self - .elems_mut() + self.elems_mut() .zip(&mut state.children) .zip(layout.children()) - { - e.as_widget_mut().operate(s, l, renderer, operation); - } + .for_each(|((e, s), l)| { + e.as_widget_mut().operate(s, l, renderer, operation); + }); } fn overlay<'b>( @@ -313,27 +314,13 @@ impl<'a, Message: Clone + 'static> Widget Option> { - let mut layouts = layout.children(); - let mut try_overlay = |elem: &'b mut Element<'a, Message>, - state: &'b mut tree::Tree| - -> Option< - iced_core::overlay::Element<'b, Message, crate::Theme, crate::Renderer>, - > { - elem.as_widget_mut() - .overlay(state, layouts.next()?, renderer, viewport, translation) - }; - - if let Some(center) = &mut self.center { - let (start_slice, end_center) = state.children.split_at_mut(1); - let (end_slice, center_slice) = end_center.split_at_mut(1); - try_overlay(&mut self.start, &mut start_slice[0]) - .or_else(|| try_overlay(&mut self.end, &mut end_slice[0])) - .or_else(|| try_overlay(center, &mut center_slice[0])) - } else { - let (start_slice, end_slice) = state.children.split_at_mut(1); - try_overlay(&mut self.start, &mut start_slice[0]) - .or_else(|| try_overlay(&mut self.end, &mut end_slice[0])) - } + self.elems_mut() + .zip(&mut state.children) + .zip(layout.children()) + .find_map(|((e, s), l)| { + e.as_widget_mut() + .overlay(s, l, renderer, viewport, translation) + }) } fn drag_destinations( @@ -343,10 +330,13 @@ impl<'a, Message: Clone + 'static> Widget HeaderBar<'a, Message> { let mut widget = HeaderBarWidget::new(start, center, end) .apply(widget::container) - .class(crate::theme::Container::HeaderBar { + .class(theme::Container::HeaderBar { focused: self.focused, sharp_corners: self.sharp_corners, transparent: self.transparent, @@ -463,7 +453,7 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> { widget::icon::from_name($name) .apply(widget::button::icon) .padding(8) - .class(crate::theme::Button::HeaderBar) + .class(theme::Button::HeaderBar) .selected(self.focused) .icon_size($size) .on_press($on_press) diff --git a/src/widget/list/column.rs b/src/widget/list/column.rs index 136b49ea..945b9140 100644 --- a/src/widget/list/column.rs +++ b/src/widget/list/column.rs @@ -63,7 +63,7 @@ impl<'a, Message: 'static> ListColumn<'a, Message> { } // Ensure a minimum height of 32. - let list_item = iced::widget::row![ + let list_item = crate::widget::row![ container(item).align_y(iced::Alignment::Center), vertical().height(iced::Length::Fixed(32.)) ] diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 0f607240..ef212dab 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -24,7 +24,7 @@ //! .on_press(Message::LaunchUrl(REPOSITORY)) //! .padding(0); //! -//! let content = widget::column() +//! let content = widget::column::with_capacity(3) //! .push(widget::icon::from_name("my-app-icon")) //! .push(widget::text::title3("My App Name")) //! .push(link) @@ -53,6 +53,9 @@ pub use iced::widget::{Canvas, canvas}; #[doc(inline)] pub use iced::widget::{Checkbox, checkbox}; +#[doc(inline)] +pub use iced::widget::{Column, column}; + #[doc(inline)] pub use iced::widget::{ComboBox, combo_box}; @@ -80,6 +83,9 @@ pub use iced::widget::{ProgressBar, progress_bar}; #[doc(inline)] pub use iced::widget::{Responsive, responsive}; +#[doc(inline)] +pub use iced::widget::{Row, row}; + #[doc(inline)] pub use iced::widget::{Slider, VerticalSlider, slider, vertical_slider}; @@ -135,34 +141,6 @@ pub mod context_drawer; #[doc(inline)] pub use context_drawer::{ContextDrawer, context_drawer}; -#[doc(inline)] -pub use column::{Column, column}; -pub mod column { - //! A container which aligns its children in a column. - - pub type Column<'a, Message> = iced::widget::Column<'a, Message, crate::Theme, crate::Renderer>; - - #[must_use] - /// A container which aligns its children in a column. - pub fn column<'a, Message>() -> Column<'a, Message> { - Column::new() - } - - #[must_use] - /// A pre-allocated [`column`]. - pub fn with_capacity<'a, Message>(capacity: usize) -> Column<'a, Message> { - Column::with_capacity(capacity) - } - - #[must_use] - /// A [`column`] that will be assigned an [`Iterator`] of children. - pub fn with_children<'a, Message>( - children: impl IntoIterator>, - ) -> Column<'a, Message> { - Column::with_children(children) - } -} - pub mod layer_container; #[doc(inline)] pub use layer_container::{LayerContainer, layer_container}; @@ -287,35 +265,6 @@ pub mod rectangle_tracker; #[doc(inline)] pub use rectangle_tracker::{RectangleTracker, rectangle_tracking_container}; -#[doc(inline)] -pub use row::{Row, row}; - -pub mod row { - //! A container which aligns its children in a row. - - pub type Row<'a, Message> = iced::widget::Row<'a, Message, crate::Theme, crate::Renderer>; - - #[must_use] - /// A container which aligns its children in a row. - pub fn row<'a, Message>() -> Row<'a, Message> { - Row::new() - } - - #[must_use] - /// A pre-allocated [`row`]. - pub fn with_capacity<'a, Message>(capacity: usize) -> Row<'a, Message> { - Row::with_capacity(capacity) - } - - #[must_use] - /// A [`row`] that will be assigned an [`Iterator`] of children. - pub fn with_children<'a, Message>( - children: impl IntoIterator>, - ) -> Row<'a, Message> { - Row::with_children(children) - } -} - pub mod scrollable; #[doc(inline)] pub use scrollable::scrollable; diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 203fbc2e..b9d1000e 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -305,7 +305,7 @@ where { self.context_menu = context_menu.map(|menus| { vec![menu::Tree::with_children( - crate::Element::from(crate::widget::row::<'static, Message>()), + crate::Element::from(crate::widget::Row::new()), menus, )] }); @@ -1481,7 +1481,7 @@ where } } } else { - if let Item::Tab(key) = std::mem::replace(&mut state.hovered, Item::None) { + if let Item::Tab(_key) = std::mem::replace(&mut state.hovered, Item::None) { for key in self.model.order.iter().copied() { self.update_entity_paragraph(state, key); } @@ -2139,7 +2139,7 @@ where tree: &'b mut Tree, layout: iced_core::Layout<'b>, _renderer: &Renderer, - viewport: &iced_core::Rectangle, + _viewport: &iced_core::Rectangle, translation: Vector, ) -> Option> { let state = tree.state.downcast_mut::(); diff --git a/src/widget/settings/item.rs b/src/widget/settings/item.rs index 110ab7b7..349d93d8 100644 --- a/src/widget/settings/item.rs +++ b/src/widget/settings/item.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::{ - Element, theme, + Element, Theme, theme, widget::{FlexRow, Row, column, container, flex_row, row, text}, }; use derive_setters::Setters; @@ -18,12 +18,12 @@ use taffy::AlignContent; pub fn item<'a, Message: 'static>( title: impl Into> + 'a, widget: impl Into> + 'a, -) -> Row<'a, Message> { +) -> Row<'a, Message, Theme> { #[inline(never)] fn inner<'a, Message: 'static>( title: Cow<'a, str>, widget: Element<'a, Message>, - ) -> Row<'a, Message> { + ) -> Row<'a, Message, Theme> { item_row(vec![ text(title).wrapping(Wrapping::Word).into(), space::horizontal().into(), @@ -37,7 +37,7 @@ pub fn item<'a, Message: 'static>( /// A settings item aligned in a row #[must_use] #[allow(clippy::module_name_repetitions)] -pub fn item_row(children: Vec>) -> Row { +pub fn item_row(children: Vec>) -> Row { row::with_children(children) .spacing(theme::spacing().space_xs) .align_y(iced::Alignment::Center) @@ -105,7 +105,7 @@ pub struct Item<'a, Message> { impl<'a, Message: 'static> Item<'a, Message> { /// Assigns a control to the item. - pub fn control(self, widget: impl Into>) -> Row<'a, Message> { + pub fn control(self, widget: impl Into>) -> Row<'a, Message, Theme> { item_row(self.control_(widget.into())) } @@ -142,7 +142,7 @@ impl<'a, Message: 'static> Item<'a, Message> { self, is_checked: bool, message: impl Fn(bool) -> Message + 'static, - ) -> Row<'a, Message> { + ) -> Row<'a, Message, Theme> { self.control( crate::widget::toggler(is_checked) .width(Length::Shrink) diff --git a/src/widget/settings/mod.rs b/src/widget/settings/mod.rs index 597d9bdd..79d81697 100644 --- a/src/widget/settings/mod.rs +++ b/src/widget/settings/mod.rs @@ -8,10 +8,10 @@ pub use self::item::{flex_item, flex_item_row, item, item_row}; pub use self::section::{Section, section}; use crate::widget::{Column, column}; -use crate::{Element, theme}; +use crate::{Element, Theme, theme}; /// A column with a predefined style for creating a settings panel #[must_use] -pub fn view_column(children: Vec>) -> Column { +pub fn view_column(children: Vec>) -> Column { column::with_children(children).spacing(theme::spacing().space_m) } diff --git a/src/widget/table/widget/compact.rs b/src/widget/table/widget/compact.rs index db71a1af..65ac9058 100644 --- a/src/widget/table/widget/compact.rs +++ b/src/widget/table/widget/compact.rs @@ -65,7 +65,7 @@ where let selected = val.model.is_active(entity); let context_menu = (val.item_context_builder)(item); - widget::column() + widget::column::with_capacity(2) .spacing(val.item_spacing) .push( widget::divider::horizontal::default() @@ -73,7 +73,7 @@ where .padding(val.divider_padding), ) .push( - widget::row() + widget::row::with_capacity(2) .spacing(space_xxxs) .align_y(Alignment::Center) .push_maybe( @@ -81,7 +81,7 @@ where .map(|icon| icon.size(val.icon_size)), ) .push( - widget::column() + widget::column::with_capacity(2) .push(widget::text::body(item.get_text(Category::default()))) .push({ let mut elements = val diff --git a/src/widget/table/widget/standard.rs b/src/widget/table/widget/standard.rs index 1fa611f3..9ab76c9d 100644 --- a/src/widget/table/widget/standard.rs +++ b/src/widget/table/widget/standard.rs @@ -99,7 +99,7 @@ where }; // Build the category header - widget::row() + widget::row::with_capacity(2) .spacing(val.icon_spacing) .push(widget::text::heading(category.to_string())) .push_maybe(match sort_state { @@ -152,7 +152,7 @@ where categories .iter() .map(|category| { - widget::row() + widget::row::with_capacity(2) .spacing(val.icon_spacing) .push_maybe( item.get_icon(*category) diff --git a/src/widget/toaster/mod.rs b/src/widget/toaster/mod.rs index efd93a9d..bafaa9f9 100644 --- a/src/widget/toaster/mod.rs +++ b/src/widget/toaster/mod.rs @@ -34,10 +34,10 @@ pub fn toaster<'a, Message: Clone + 'static>( } = theme.cosmic().spacing; let make_toast = move |(id, toast): (ToastId, &'a Toast)| { - let row = row() + let row = row::with_capacity(2) .push(text(&toast.message)) .push( - row() + row::with_capacity(2) .push_maybe(toast.action.as_ref().map(|action| { button::text(&action.description).on_press((action.message)(id)) }))