feat(list_column): add drag and drop support to widget API

This commit is contained in:
黑嫖233 2026-06-16 23:35:59 +08:00 committed by GitHub
parent f79ccb8cba
commit 8df1858e5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,7 +3,7 @@
use crate::widget::container::Catalog; use crate::widget::container::Catalog;
use crate::widget::space::vertical; use crate::widget::space::vertical;
use crate::widget::{button, column, container, divider, row}; use crate::widget::{DndDestination, DndSource, button, column, container, divider, row};
use crate::{Apply, Element, theme}; use crate::{Apply, Element, theme};
use iced::{Length, Padding}; use iced::{Length, Padding};
@ -11,14 +11,23 @@ use iced::{Length, Padding};
pub struct ListButton<'a, Message> { pub struct ListButton<'a, Message> {
content: Element<'a, Message>, content: Element<'a, Message>,
on_press: Option<Message>, on_press: Option<Message>,
dnd_source_builder: Option<Box<DndSourceBuilder<'a, Message>>>,
dnd_destination_builder: Option<Box<DndDestinationBuilder<'a, Message>>>,
selected: bool, selected: bool,
} }
/// Builds a DndSource, wrapping an element
pub type DndSourceBuilder<'a, Message> = dyn FnOnce(Element<'a, Message>) -> DndSource<'a, Message, Box<dyn iced::clipboard::mime::AsMimeTypes + Send>>;
/// Builds a DndDestination, wrapping an element
pub type DndDestinationBuilder<'a, Message> = dyn FnOnce(Element<'a, Message>) -> DndDestination<'a, Message>;
/// Creates a [`ListButton`] with the given content. /// Creates a [`ListButton`] with the given content.
pub fn button<'a, Message>(content: impl Into<Element<'a, Message>>) -> ListButton<'a, Message> { pub fn button<'a, Message>(content: impl Into<Element<'a, Message>>) -> ListButton<'a, Message> {
ListButton { ListButton {
content: content.into(), content: content.into(),
on_press: None, on_press: None,
dnd_source_builder: None,
dnd_destination_builder: None,
selected: false, selected: false,
} }
} }
@ -38,6 +47,16 @@ impl<'a, Message: 'static> ListButton<'a, Message> {
self.selected = selected; self.selected = selected;
self self
} }
pub fn with_dnd_source(mut self, builder: Box<DndSourceBuilder<'a, Message>>) -> Self {
self.dnd_source_builder = Some(builder);
self
}
pub fn with_dnd_destination(mut self, builder: Box<DndDestinationBuilder<'a, Message>>) -> Self {
self.dnd_destination_builder = Some(builder);
self
}
} }
pub enum ListItem<'a, Message> { pub enum ListItem<'a, Message> {
@ -175,19 +194,32 @@ impl<'a, Message: Clone + 'static> ListColumn<'a, Message> {
content, content,
on_press, on_press,
selected, selected,
}) => col.push( dnd_source_builder,
content_row(content) dnd_destination_builder,
.apply(button::custom) }) => {
.padding(item_padding) let mut button: Element<'a, Message> =
.width(Length::Fill) content_row(content)
.on_press_maybe(on_press) .apply(button::custom)
.selected(selected) .padding(item_padding)
.class(theme::Button::ListItem(get_radius( .width(Length::Fill)
radius_s, .on_press_maybe(on_press)
i == 0, .selected(selected)
i == last_index, .class(theme::Button::ListItem(get_radius(
))), radius_s,
), i == 0,
i == last_index,
)))
.into();
if let Some(builder) = dnd_source_builder {
button = builder(button).into();
}
if let Some(builder) = dnd_destination_builder {
button = builder(button).into();
}
col.push(button)
},
}; };
} }