From 2777de3c7d440de50bc16ee1062b05dc39c994dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Wed, 16 Jul 2025 00:10:05 +0200 Subject: [PATCH] Add interactive controls to `table` example --- examples/table/src/main.rs | 98 +++++++++++++++++++++++++++++++++----- widget/src/table.rs | 61 +++++++----------------- 2 files changed, 102 insertions(+), 57 deletions(-) diff --git a/examples/table/src/main.rs b/examples/table/src/main.rs index f642c2e1..896dac93 100644 --- a/examples/table/src/main.rs +++ b/examples/table/src/main.rs @@ -1,7 +1,10 @@ use iced::font; use iced::time::{Duration, hours, minutes}; -use iced::widget::{center, scrollable, table, text}; -use iced::{Element, Fill, Font}; +use iced::widget::{ + center, center_x, column, container, row, scrollable, slider, table, text, + tooltip, +}; +use iced::{Center, Element, Fill, Font}; pub fn main() -> iced::Result { iced::application(Table::new, Table::update, Table::view).run() @@ -9,20 +12,30 @@ pub fn main() -> iced::Result { struct Table { events: Vec, + padding: (f32, f32), + separator: (f32, f32), } #[derive(Debug, Clone)] -enum Message {} +enum Message { + PaddingChanged(f32, f32), + SeparatorChanged(f32, f32), +} impl Table { fn new() -> Self { Self { events: Event::list(), + padding: (10.0, 5.0), + separator: (1.0, 1.0), } } fn update(&mut self, message: Message) { - match message {} + match message { + Message::PaddingChanged(x, y) => self.padding = (x, y), + Message::SeparatorChanged(x, y) => self.separator = (x, y), + } } fn view(&self) -> Element<'_, Message> { @@ -34,18 +47,79 @@ impl Table { }) }; - let columns = table::definition() - .column(bold("Name"), |event: &Event| { + let columns = [ + table::column(bold("Name"), |event: &Event| { text(&event.name).width(Fill) - }) - .column(bold("Time"), |event| text!("{:?}", event.duration)) - .column(bold("Price"), |event| text!("{:.2}", event.price)) - .column(bold("Rating"), |event| text!("{:.2}", event.rating)); + }), + table::column(bold("Time"), |event: &Event| { + text!("{} min", event.duration.as_secs() / 60) + }), + table::column(bold("Price"), |event: &Event| { + if event.price > 0.0 { + text!("${:.2}", event.price) + } else { + text("Free") + } + }), + table::column(bold("Rating"), |event: &Event| { + text!("{:.2}", event.rating) + }), + ]; - table(columns, &self.events).width(640).padding_y(5) + table(columns, &self.events) + .width(640) + .padding_x(self.padding.0) + .padding_y(self.padding.1) + .separator_x(self.separator.0) + .separator_y(self.separator.1) }; - center(scrollable(table).spacing(10)).padding(10).into() + let controls = { + let labeled_slider = + |label, + range: std::ops::RangeInclusive, + (x, y), + on_change: fn(f32, f32) -> Message| { + row![ + text(label).font(Font::MONOSPACE).size(14).width(200), + tooltip( + slider(range.clone(), x, move |x| on_change(x, y)), + text!("{x:.0}px").font(Font::MONOSPACE).size(10), + tooltip::Position::Left + ), + tooltip( + slider(range, y, move |y| on_change(x, y)), + text!("{y:.0}px").font(Font::MONOSPACE).size(10), + tooltip::Position::Right + ), + ] + .spacing(10) + .align_y(Center) + }; + + column![ + labeled_slider( + "Padding", + 0.0..=30.0, + self.padding, + Message::PaddingChanged + ), + labeled_slider( + "Separator", + 0.0..=5.0, + self.separator, + Message::SeparatorChanged + ) + ] + .spacing(10) + .width(640) + }; + + column![ + center(scrollable(table).spacing(10)).padding(10), + center_x(controls).padding(10).style(container::dark) + ] + .into() } } diff --git a/widget/src/table.rs b/widget/src/table.rs index eda54bce..49f2813b 100644 --- a/widget/src/table.rs +++ b/widget/src/table.rs @@ -21,13 +21,6 @@ where Table::new(columns, rows) } -pub fn definition<'a, T, Message, Theme, Renderer>() --> Definition<'a, T, Message, Theme, Renderer> { - Definition { - columns: Vec::new(), - } -} - pub fn column<'a, T, E, Message, Theme, Renderer>( header: impl Into>, view: impl Fn(T) -> E + 'a, @@ -133,6 +126,22 @@ where self.padding_y = padding.into().0; self } + + pub fn separator(self, separator: impl Into) -> Self { + let separator = separator.into(); + + self.separator_x(separator).separator_y(separator) + } + + pub fn separator_x(mut self, separator: impl Into) -> Self { + self.separator_x = separator.into().0; + self + } + + pub fn separator_y(mut self, separator: impl Into) -> Self { + self.separator_y = separator.into().0; + self + } } pub struct Metrics { @@ -452,44 +461,6 @@ where } } -pub struct Definition< - 'a, - T, - Message, - Theme = crate::Theme, - Renderer = crate::Renderer, -> { - columns: Vec>, -} - -impl<'a, T, Message, Theme, Renderer> - Definition<'a, T, Message, Theme, Renderer> -{ - pub fn column( - mut self, - header: impl Into>, - view: impl Fn(T) -> E + 'a, - ) -> Self - where - T: 'a, - E: Into>, - { - self.columns.push(column(header, view)); - self - } -} - -impl<'a, T, Message, Theme, Renderer> IntoIterator - for Definition<'a, T, Message, Theme, Renderer> -{ - type Item = Column<'a, T, Message, Theme, Renderer>; - type IntoIter = ::std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.columns.into_iter() - } -} - pub struct Column< 'a, T,