Respect column width in table widget
This commit is contained in:
parent
2777de3c7d
commit
1e89439aff
3 changed files with 128 additions and 70 deletions
|
|
@ -452,6 +452,13 @@ pub fn success(theme: &Theme) -> Style {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Text conveying some mildly negative information, like a warning.
|
||||||
|
pub fn warning(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.palette().warning),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Text conveying some negative information, like an error.
|
/// Text conveying some negative information, like an error.
|
||||||
pub fn danger(theme: &Theme) -> Style {
|
pub fn danger(theme: &Theme) -> Style {
|
||||||
Style {
|
Style {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
use iced::font;
|
use iced::font;
|
||||||
use iced::time::{Duration, hours, minutes};
|
use iced::time::{Duration, hours, minutes};
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
center, center_x, column, container, row, scrollable, slider, table, text,
|
center_x, center_y, column, container, row, scrollable, slider, table,
|
||||||
tooltip,
|
text, tooltip,
|
||||||
};
|
};
|
||||||
use iced::{Center, Element, Fill, Font};
|
use iced::{Center, Element, Font, Theme};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
iced::application(Table::new, Table::update, Table::view).run()
|
iced::application(Table::new, Table::update, Table::view)
|
||||||
|
.theme(|_| Theme::CatppuccinMocha)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Table {
|
struct Table {
|
||||||
|
|
@ -48,26 +50,41 @@ impl Table {
|
||||||
};
|
};
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
table::column(bold("Name"), |event: &Event| {
|
table::column(bold("Name"), |event: &Event| text(&event.name)),
|
||||||
text(&event.name).width(Fill)
|
|
||||||
}),
|
|
||||||
table::column(bold("Time"), |event: &Event| {
|
table::column(bold("Time"), |event: &Event| {
|
||||||
text!("{} min", event.duration.as_secs() / 60)
|
let minutes = event.duration.as_secs() / 60;
|
||||||
|
|
||||||
|
text!("{minutes} min").style(if minutes > 90 {
|
||||||
|
text::warning
|
||||||
|
} else {
|
||||||
|
text::default
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
table::column(bold("Price"), |event: &Event| {
|
table::column(bold("Price"), |event: &Event| {
|
||||||
if event.price > 0.0 {
|
if event.price > 0.0 {
|
||||||
text!("${:.2}", event.price)
|
text!("${:.2}", event.price).style(
|
||||||
|
if event.price > 100.0 {
|
||||||
|
text::warning
|
||||||
|
} else {
|
||||||
|
text::default
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
text("Free")
|
text("Free").style(text::success)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
table::column(bold("Rating"), |event: &Event| {
|
table::column(bold("Rating"), |event: &Event| {
|
||||||
text!("{:.2}", event.rating)
|
text!("{:.2}", event.rating).style(if event.rating > 4.7 {
|
||||||
|
text::success
|
||||||
|
} else if event.rating < 2.0 {
|
||||||
|
text::danger
|
||||||
|
} else {
|
||||||
|
text::default
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
table(columns, &self.events)
|
table(columns, &self.events)
|
||||||
.width(640)
|
|
||||||
.padding_x(self.padding.0)
|
.padding_x(self.padding.0)
|
||||||
.padding_y(self.padding.1)
|
.padding_y(self.padding.1)
|
||||||
.separator_x(self.separator.0)
|
.separator_x(self.separator.0)
|
||||||
|
|
@ -81,7 +98,7 @@ impl Table {
|
||||||
(x, y),
|
(x, y),
|
||||||
on_change: fn(f32, f32) -> Message| {
|
on_change: fn(f32, f32) -> Message| {
|
||||||
row![
|
row![
|
||||||
text(label).font(Font::MONOSPACE).size(14).width(200),
|
text(label).font(Font::MONOSPACE).size(14).width(100),
|
||||||
tooltip(
|
tooltip(
|
||||||
slider(range.clone(), x, move |x| on_change(x, y)),
|
slider(range.clone(), x, move |x| on_change(x, y)),
|
||||||
text!("{x:.0}px").font(Font::MONOSPACE).size(10),
|
text!("{x:.0}px").font(Font::MONOSPACE).size(10),
|
||||||
|
|
@ -112,11 +129,11 @@ impl Table {
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.width(640)
|
.width(400)
|
||||||
};
|
};
|
||||||
|
|
||||||
column![
|
column![
|
||||||
center(scrollable(table).spacing(10)).padding(10),
|
center_y(scrollable(center_x(table)).spacing(10)).padding(10),
|
||||||
center_x(controls).padding(10).style(container::dark)
|
center_x(controls).padding(10).style(container::dark)
|
||||||
]
|
]
|
||||||
.into()
|
.into()
|
||||||
|
|
|
||||||
|
|
@ -73,28 +73,33 @@ where
|
||||||
columns.size_hint().0 * (1 + rows.size_hint().0),
|
columns.size_hint().0 * (1 + rows.size_hint().0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut columns: Vec<_> = columns
|
||||||
|
.into_iter()
|
||||||
|
.map(|column| {
|
||||||
|
cells.push(column.header);
|
||||||
|
cells.extend(rows.clone().map(|row| {
|
||||||
|
let cell = (column.view)(row);
|
||||||
|
let size_hint = cell.as_widget().size_hint();
|
||||||
|
|
||||||
|
height = height.enclose(size_hint.height);
|
||||||
|
|
||||||
|
cell
|
||||||
|
}));
|
||||||
|
|
||||||
|
width = width.enclose(column.width);
|
||||||
|
|
||||||
|
column.width
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if width == Length::Shrink {
|
||||||
|
if let Some(first) = columns.first_mut() {
|
||||||
|
*first = Length::Fill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
columns: columns
|
columns,
|
||||||
.into_iter()
|
|
||||||
.map(|column| {
|
|
||||||
let mut column_width = column.width;
|
|
||||||
|
|
||||||
cells.push(column.header);
|
|
||||||
cells.extend(rows.clone().map(|row| {
|
|
||||||
let cell = (column.view)(row);
|
|
||||||
let size_hint = cell.as_widget().size_hint();
|
|
||||||
|
|
||||||
column_width = column_width.enclose(size_hint.width);
|
|
||||||
height = height.enclose(size_hint.height);
|
|
||||||
|
|
||||||
cell
|
|
||||||
}));
|
|
||||||
|
|
||||||
width = width.enclose(column_width);
|
|
||||||
|
|
||||||
column_width
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
cells,
|
cells,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|
@ -191,9 +196,11 @@ where
|
||||||
limits: &layout::Limits,
|
limits: &layout::Limits,
|
||||||
) -> layout::Node {
|
) -> layout::Node {
|
||||||
let metrics = tree.state.downcast_mut::<Metrics>();
|
let metrics = tree.state.downcast_mut::<Metrics>();
|
||||||
let limits = limits.width(self.width).height(self.height);
|
|
||||||
let rows = self.cells.len() / self.columns.len();
|
let rows = self.cells.len() / self.columns.len();
|
||||||
|
|
||||||
|
let limits = limits.width(self.width).height(self.height);
|
||||||
let available = limits.max();
|
let available = limits.max();
|
||||||
|
let table_fluid = self.width.fluid();
|
||||||
|
|
||||||
let mut cells = Vec::with_capacity(self.cells.len());
|
let mut cells = Vec::with_capacity(self.cells.len());
|
||||||
cells.resize(self.cells.len(), layout::Node::default());
|
cells.resize(self.cells.len(), layout::Node::default());
|
||||||
|
|
@ -217,14 +224,27 @@ where
|
||||||
{
|
{
|
||||||
let column = i / rows;
|
let column = i / rows;
|
||||||
let row = i % rows;
|
let row = i % rows;
|
||||||
|
|
||||||
|
let width = self.columns[column];
|
||||||
let size = cell.as_widget().size();
|
let size = cell.as_widget().size();
|
||||||
|
|
||||||
if size.width.fill_factor() != 0 || size.height.fill_factor() != 0 {
|
if row == 0 {
|
||||||
column_factors[column] =
|
y = self.padding_y;
|
||||||
column_factors[column].max(size.width.fill_factor());
|
|
||||||
|
|
||||||
row_factors[row] =
|
if column > 0 {
|
||||||
row_factors[row].max(size.height.fill_factor());
|
x += metrics.columns[column - 1] + spacing_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let width_factor =
|
||||||
|
width.fill_factor().max(size.width.fill_factor());
|
||||||
|
let height_factor = size.height.fill_factor();
|
||||||
|
|
||||||
|
if width_factor != 0 || height_factor != 0 {
|
||||||
|
column_factors[column] =
|
||||||
|
column_factors[column].max(width_factor);
|
||||||
|
|
||||||
|
row_factors[row] = row_factors[row].max(height_factor);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -233,24 +253,16 @@ where
|
||||||
Size::ZERO,
|
Size::ZERO,
|
||||||
Size::new(available.width - x, available.height - y),
|
Size::new(available.width - x, available.height - y),
|
||||||
)
|
)
|
||||||
.width(self.columns[i / rows]);
|
.width(width);
|
||||||
|
|
||||||
let layout = cell.as_widget().layout(state, renderer, &limits);
|
let layout = cell.as_widget().layout(state, renderer, &limits);
|
||||||
let size = layout.size();
|
let size = limits.resolve(width, Length::Shrink, layout.size());
|
||||||
|
|
||||||
metrics.columns[column] = metrics.columns[column].max(size.width);
|
metrics.columns[column] = metrics.columns[column].max(size.width);
|
||||||
metrics.rows[row] = metrics.rows[row].max(size.height);
|
metrics.rows[row] = metrics.rows[row].max(size.height);
|
||||||
cells[i] = layout;
|
cells[i] = layout;
|
||||||
|
|
||||||
if row == 0 {
|
y += size.height + spacing_y;
|
||||||
y = self.padding_y;
|
|
||||||
|
|
||||||
if column > 0 {
|
|
||||||
x += metrics.columns[column - 1] + spacing_x;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
y += size.height + spacing_y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SECOND PASS
|
// SECOND PASS
|
||||||
|
|
@ -292,20 +304,42 @@ where
|
||||||
{
|
{
|
||||||
let column = i / rows;
|
let column = i / rows;
|
||||||
let row = i % rows;
|
let row = i % rows;
|
||||||
|
|
||||||
let size = cell.as_widget().size();
|
let size = cell.as_widget().size();
|
||||||
|
|
||||||
if size.width.fill_factor() != 0 || size.height.fill_factor() != 0 {
|
let width = self.columns[column];
|
||||||
let column_factor = column_factors[column];
|
let width_factor = width.fill_factor();
|
||||||
|
|
||||||
|
if row == 0 {
|
||||||
|
y = self.padding_y;
|
||||||
|
|
||||||
|
if column > 0 {
|
||||||
|
x += metrics.columns[column - 1] + spacing_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if width_factor != 0
|
||||||
|
|| size.width.fill_factor() != 0
|
||||||
|
|| size.height.fill_factor() != 0
|
||||||
|
{
|
||||||
let row_factor = row_factors[row];
|
let row_factor = row_factors[row];
|
||||||
|
|
||||||
let max_width = if column_factor == 0 {
|
let max_width = if width_factor == 0 {
|
||||||
(available.width - x).max(0.0)
|
if size.width.is_fill() {
|
||||||
|
metrics.columns[column]
|
||||||
|
} else {
|
||||||
|
(available.width - x).max(0.0)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
width_unit * column_factor as f32
|
width_unit * width_factor as f32
|
||||||
};
|
};
|
||||||
|
|
||||||
let max_height = if row_factor == 0 {
|
let max_height = if row_factor == 0 {
|
||||||
(available.height - y).max(0.0)
|
if size.height.is_fill() {
|
||||||
|
metrics.rows[row]
|
||||||
|
} else {
|
||||||
|
(available.height - y).max(0.0)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
height_unit * row_factor as f32
|
height_unit * row_factor as f32
|
||||||
};
|
};
|
||||||
|
|
@ -314,25 +348,25 @@ where
|
||||||
Size::ZERO,
|
Size::ZERO,
|
||||||
Size::new(max_width, max_height),
|
Size::new(max_width, max_height),
|
||||||
)
|
)
|
||||||
.width(self.columns[i / rows]);
|
.width(width);
|
||||||
|
|
||||||
let layout = cell.as_widget().layout(state, renderer, &limits);
|
let layout = cell.as_widget().layout(state, renderer, &limits);
|
||||||
let size = layout.size();
|
let size = limits.resolve(
|
||||||
|
if let Length::Fixed(_) = width {
|
||||||
|
width
|
||||||
|
} else {
|
||||||
|
table_fluid
|
||||||
|
},
|
||||||
|
Length::Shrink,
|
||||||
|
layout.size(),
|
||||||
|
);
|
||||||
|
|
||||||
metrics.columns[column] =
|
metrics.columns[column] =
|
||||||
metrics.columns[column].max(size.width);
|
metrics.columns[column].max(size.width);
|
||||||
metrics.rows[row] = metrics.rows[row].max(size.height);
|
metrics.rows[row] = metrics.rows[row].max(size.height);
|
||||||
cells[i] = layout;
|
cells[i] = layout;
|
||||||
}
|
|
||||||
|
|
||||||
if row == 0 {
|
y += size.height + spacing_y;
|
||||||
y = self.padding_y;
|
|
||||||
|
|
||||||
if column > 0 {
|
|
||||||
x += metrics.columns[column - 1] + spacing_x;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
y += cells[i].size().height + spacing_y;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue