Add interactive controls to table example

This commit is contained in:
Héctor Ramón Jiménez 2025-07-16 00:10:05 +02:00
parent 931ed20cf8
commit 2777de3c7d
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 102 additions and 57 deletions

View file

@ -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<Event>,
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<f32>,
(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()
}
}

View file

@ -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<Element<'a, Message, Theme, Renderer>>,
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<Pixels>) -> Self {
let separator = separator.into();
self.separator_x(separator).separator_y(separator)
}
pub fn separator_x(mut self, separator: impl Into<Pixels>) -> Self {
self.separator_x = separator.into().0;
self
}
pub fn separator_y(mut self, separator: impl Into<Pixels>) -> 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<Column<'a, T, Message, Theme, Renderer>>,
}
impl<'a, T, Message, Theme, Renderer>
Definition<'a, T, Message, Theme, Renderer>
{
pub fn column<E>(
mut self,
header: impl Into<Element<'a, Message, Theme, Renderer>>,
view: impl Fn(T) -> E + 'a,
) -> Self
where
T: 'a,
E: Into<Element<'a, Message, Theme, Renderer>>,
{
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<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.columns.into_iter()
}
}
pub struct Column<
'a,
T,