Make grid sizing strategy explicit and more intuitive
This commit is contained in:
parent
504d9c2959
commit
687750e026
4 changed files with 74 additions and 28 deletions
|
|
@ -22,6 +22,10 @@ use std::collections::HashMap;
|
|||
|
||||
fn main() -> iced::Result {
|
||||
iced::application(Gallery::new, Gallery::update, Gallery::view)
|
||||
.window_size((
|
||||
Preview::WIDTH as f32 * 4.0,
|
||||
Preview::HEIGHT as f32 * 2.5,
|
||||
))
|
||||
.subscription(Gallery::subscription)
|
||||
.theme(Gallery::theme)
|
||||
.run()
|
||||
|
|
@ -183,7 +187,7 @@ impl Gallery {
|
|||
|
||||
let gallery = grid(images)
|
||||
.fluid(Preview::WIDTH)
|
||||
.ratio(Preview::WIDTH as f32 / Preview::HEIGHT as f32)
|
||||
.height(grid::aspect_ratio(Preview::WIDTH, Preview::HEIGHT))
|
||||
.spacing(10);
|
||||
|
||||
let content = container(scrollable(gallery).spacing(10)).padding(10);
|
||||
|
|
@ -225,7 +229,7 @@ fn card<'a>(
|
|||
horizontal_space().into()
|
||||
};
|
||||
|
||||
let card = mouse_area(container(image).height(Fill).style(container::dark))
|
||||
let card = mouse_area(container(image).style(container::dark))
|
||||
.on_enter(Message::ThumbnailHovered(metadata.id, true))
|
||||
.on_exit(Message::ThumbnailHovered(metadata.id, false));
|
||||
|
||||
|
|
@ -245,10 +249,7 @@ fn card<'a>(
|
|||
}
|
||||
|
||||
fn placeholder<'a>() -> Element<'a, Message> {
|
||||
container(horizontal_space())
|
||||
.height(Fill)
|
||||
.style(container::dark)
|
||||
.into()
|
||||
container(horizontal_space()).style(container::dark).into()
|
||||
}
|
||||
|
||||
enum Preview {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub struct Grid<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer> {
|
|||
spacing: f32,
|
||||
columns: Constraint,
|
||||
width: Option<Pixels>,
|
||||
ratio: Option<Pixels>,
|
||||
height: Sizing,
|
||||
children: Vec<Element<'a, Message, Theme, Renderer>>,
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ where
|
|||
spacing: 0.0,
|
||||
columns: Constraint::Amount(3),
|
||||
width: None,
|
||||
ratio: None,
|
||||
height: Sizing::AspectRatio(1.0),
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +76,14 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the [`Grid`].
|
||||
///
|
||||
/// By default, a [`Grid`] uses a cell aspect ratio of `1.0` (i.e. squares).
|
||||
pub fn height(mut self, height: impl Into<Sizing>) -> Self {
|
||||
self.height = height.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the amount of columns in the [`Grid`].
|
||||
pub fn columns(mut self, column: usize) -> Self {
|
||||
self.columns = Constraint::Amount(column);
|
||||
|
|
@ -89,12 +97,6 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the amount of horizontal pixels per each vertical pixel of a cell in the [`Grid`].
|
||||
pub fn ratio(mut self, ratio: impl Into<Pixels>) -> Self {
|
||||
self.ratio = Some(ratio.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an [`Element`] to the [`Grid`].
|
||||
pub fn push(
|
||||
mut self,
|
||||
|
|
@ -166,7 +168,10 @@ where
|
|||
.width
|
||||
.map(|pixels| Length::Fixed(pixels.0))
|
||||
.unwrap_or(Length::Fill),
|
||||
height: Length::Shrink,
|
||||
height: match self.height {
|
||||
Sizing::AspectRatio(_) => Length::Shrink,
|
||||
Sizing::EvenlyDistribute(length) => length,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -194,22 +199,23 @@ where
|
|||
- self.spacing * (cells_per_row - 1) as f32)
|
||||
/ cells_per_row as f32;
|
||||
|
||||
let cell_height = if let Some(ratio) = self.ratio {
|
||||
cell_width / ratio.0
|
||||
} else if available.height.is_finite() {
|
||||
available.height / total_rows as f32
|
||||
} else {
|
||||
f32::INFINITY
|
||||
let cell_height = match self.height {
|
||||
Sizing::AspectRatio(ratio) => Some(cell_width / ratio),
|
||||
Sizing::EvenlyDistribute(Length::Shrink) => None,
|
||||
Sizing::EvenlyDistribute(_) => {
|
||||
Some(available.height / total_rows as f32)
|
||||
}
|
||||
};
|
||||
|
||||
let cell_limits = layout::Limits::new(
|
||||
Size::new(cell_width, 0.0),
|
||||
Size::new(cell_width, cell_height),
|
||||
Size::new(cell_width, cell_height.unwrap_or(0.0)),
|
||||
Size::new(cell_width, cell_height.unwrap_or(available.height)),
|
||||
);
|
||||
|
||||
let mut nodes = Vec::new();
|
||||
let mut x = 0.0;
|
||||
let mut y = 0.0;
|
||||
let mut row_height = 0.0f32;
|
||||
|
||||
for (i, (child, tree)) in
|
||||
self.children.iter().zip(&mut tree.children).enumerate()
|
||||
|
|
@ -219,11 +225,15 @@ where
|
|||
.layout(tree, renderer, &cell_limits)
|
||||
.move_to((x, y));
|
||||
|
||||
x += node.size().width + self.spacing;
|
||||
let size = node.size();
|
||||
|
||||
x += size.width + self.spacing;
|
||||
row_height = row_height.max(size.height);
|
||||
|
||||
if (i + 1) % cells_per_row == 0 {
|
||||
y += cell_height + self.spacing;
|
||||
y += cell_height.unwrap_or(row_height) + self.spacing;
|
||||
x = 0.0;
|
||||
row_height = 0.0;
|
||||
}
|
||||
|
||||
nodes.push(node);
|
||||
|
|
@ -232,7 +242,7 @@ where
|
|||
if x == 0.0 {
|
||||
y -= self.spacing;
|
||||
} else {
|
||||
y += cell_height;
|
||||
y += cell_height.unwrap_or(row_height);
|
||||
}
|
||||
|
||||
layout::Node::with_children(Size::new(available.width, y), nodes)
|
||||
|
|
@ -356,3 +366,38 @@ where
|
|||
Self::new(row)
|
||||
}
|
||||
}
|
||||
|
||||
/// The sizing strategy of a [`Grid`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Sizing {
|
||||
/// The [`Grid`] will ensure each cell follows the given aspect ratio and the
|
||||
/// total size will be the sum of the cells and the spacing between them.
|
||||
///
|
||||
/// The ratio is the amount of horizontal pixels per each vertical pixel of a cell
|
||||
/// in the [`Grid`].
|
||||
AspectRatio(f32),
|
||||
|
||||
/// The [`Grid`] will evenly distribute the space available in the given [`Length`]
|
||||
/// for each cell.
|
||||
EvenlyDistribute(Length),
|
||||
}
|
||||
|
||||
impl From<f32> for Sizing {
|
||||
fn from(height: f32) -> Self {
|
||||
Self::EvenlyDistribute(Length::from(height))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Length> for Sizing {
|
||||
fn from(height: Length) -> Self {
|
||||
Self::EvenlyDistribute(height)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new [`Sizing`] strategy that maintains the given aspect ratio.
|
||||
pub fn aspect_ratio(
|
||||
width: impl Into<Pixels>,
|
||||
height: impl Into<Pixels>,
|
||||
) -> Sizing {
|
||||
Sizing::AspectRatio(width.into().0 / height.into().0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ pub use iced_runtime::core;
|
|||
|
||||
mod action;
|
||||
mod column;
|
||||
mod grid;
|
||||
mod mouse_area;
|
||||
mod pin;
|
||||
mod space;
|
||||
|
|
@ -21,6 +20,7 @@ pub mod button;
|
|||
pub mod checkbox;
|
||||
pub mod combo_box;
|
||||
pub mod container;
|
||||
pub mod grid;
|
||||
pub mod keyed;
|
||||
pub mod overlay;
|
||||
pub mod pane_grid;
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ where
|
|||
limits.max().width
|
||||
},
|
||||
if self.direction.vertical().is_some() {
|
||||
f32::MAX
|
||||
f32::INFINITY
|
||||
} else {
|
||||
limits.max().height
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue