Closed lambdadeltakay closed 7 months ago
I guess the problem is that it's still adding the item spacing for the filtered items.
A simple fix would be to set the item spacing to 0 before you call dnd:
ui.spacing_mut().item_spacing.y = 0.0;
And then optionally do the spacing for each item within the list.
Alternatively you could create a filtered vec each frame, that stores the index the item had in the original frame, and then afterwards call shift_vec with the original index. Something like this:
let mut filtered = items
.iter_mut()
// We enumerate so we can get the original index
.enumerate()
.filter(|(_, item)| item.number.to_string().contains(&filter))
.collect::<Vec<_>>();
let response = dnd(ui, "dnd").show(
filtered.iter_mut(),
|ui, (original_idx, item), handle, _dragging| {
ui.horizontal(|ui| {
let clicked = handle
.sense(Sense::click())
.ui(ui, |ui| {
ui.label("grab");
})
.clicked();
if clicked {
println!("clicked {}", item.number);
}
ui.label(&item.number.to_string());
});
},
);
if let Some(update) = response.final_update() {
// Get the original indices of the items for the update
shift_vec(filtered[update.from].0, filtered[update.to].0, &mut items);
}
This is not very efficient since you create a new vec each frame, but a bit cleaner since there are no invisible items where the dnd might want to try to fit the item between.
Let me know if one of the approaches works for you!
I've added a example showcasing two ways to filter the list. I think in theory I could also add a filter method to the dnd struct but I think it's better if the filtering is handled by the application. I'll close issue for now, let me know if it's still not working for you!
Filtering before the DND call worked perfectly as long as I manually implemented the shifting logic
Thank you
I implemented a simple filter search which just doesn't add elements if they don't match and the result is a strange gap between elements.
It seems to increase if the gap represents more elements.