mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-11-03 20:56:39 -06:00
remember children's column
This commit is contained in:
1 parent
f46cc07007
commit
ed82e94eff
1 file changed
+43
-10
@@ -1,4 +1,5 @@
|
||||
use gtk::{glib, prelude::*};
|
||||
use std::cell::RefCell;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct MasonryLayout(ObjectSubclass<imp::MasonryLayout>)
|
||||
@@ -16,7 +17,9 @@ mod imp {
|
||||
use gtk::subclass::prelude::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MasonryLayout;
|
||||
pub struct MasonryLayout {
|
||||
packing: RefCell<Packing>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for MasonryLayout {
|
||||
@@ -44,21 +47,33 @@ mod imp {
|
||||
(minimum, natural, -1, -1)
|
||||
} else {
|
||||
let width = if for_size < 0 { natural } else { for_size };
|
||||
let height = layout(widget, width, |_, _| {});
|
||||
let (height, _) = layout(widget, width, &self.packing.borrow(), |_, _| {});
|
||||
(height, height, -1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
fn allocate(&self, widget: >k::Widget, width: i32, _height: i32, _baseline: i32) {
|
||||
layout(widget, width, |child, allocation| {
|
||||
child.size_allocate(allocation, -1);
|
||||
});
|
||||
let (_, packing) = layout(
|
||||
widget,
|
||||
width,
|
||||
&self.packing.borrow(),
|
||||
|child, allocation| {
|
||||
child.size_allocate(allocation, -1);
|
||||
},
|
||||
);
|
||||
self.packing.replace(packing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SPACING: i32 = 10;
|
||||
|
||||
#[derive(Default)]
|
||||
struct Packing {
|
||||
columns: usize,
|
||||
children: Vec<(glib::WeakRef<gtk::Widget>, usize)>,
|
||||
}
|
||||
|
||||
fn children(widget: >k::Widget) -> impl Iterator<Item = gtk::Widget> {
|
||||
std::iter::successors(widget.first_child(), |child| child.next_sibling())
|
||||
.filter(|child| child.should_layout())
|
||||
@@ -84,18 +99,36 @@ fn measure_width(widget: >k::Widget) -> (i32, i32) {
|
||||
fn layout(
|
||||
widget: >k::Widget,
|
||||
width: i32,
|
||||
previous: &Packing,
|
||||
mut place: impl FnMut(>k::Widget, >k::Allocation),
|
||||
) -> i32 {
|
||||
) -> (i32, Packing) {
|
||||
let (minimum, _) = measure_width(widget);
|
||||
let columns = if children(widget).count() > 1 && width >= minimum * 2 + SPACING {
|
||||
let children: Vec<_> = children(widget).collect();
|
||||
let columns = if children.len() > 1 && width >= minimum * 2 + SPACING {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let column_width = ((width - SPACING * (columns as i32 - 1)) / columns as i32).max(0);
|
||||
let reuse = previous.columns == columns
|
||||
&& previous.children.len() == children.len()
|
||||
&& previous
|
||||
.children
|
||||
.iter()
|
||||
.zip(&children)
|
||||
.all(|((previous, _), child)| previous.upgrade().as_ref() == Some(child));
|
||||
let mut packing = Packing {
|
||||
columns,
|
||||
children: Vec::with_capacity(children.len()),
|
||||
};
|
||||
let mut heights = [0, 0];
|
||||
for child in children(widget) {
|
||||
let column = usize::from(columns == 2 && heights[1] < heights[0]);
|
||||
for (index, child) in children.into_iter().enumerate() {
|
||||
let column = if reuse {
|
||||
previous.children[index].1
|
||||
} else {
|
||||
usize::from(columns == 2 && heights[1] < heights[0])
|
||||
};
|
||||
packing.children.push((child.downgrade(), column));
|
||||
let x = column as i32 * (column_width + SPACING);
|
||||
let child_width = if column == columns - 1 {
|
||||
width - x
|
||||
@@ -112,5 +145,5 @@ fn layout(
|
||||
place(&child, >k::Allocation::new(x, y, child_width, height));
|
||||
heights[column] = y + height + SPACING;
|
||||
}
|
||||
(heights[0].max(heights[1]) - SPACING).max(0)
|
||||
((heights[0].max(heights[1]) - SPACING).max(0), packing)
|
||||
}
|
||||
Reference in new issue
Block a user