summaryrefslogtreecommitdiff
path: root/iced_drop/src/widget/operation
diff options
context:
space:
mode:
authorPolesznyák Márk László <116908301+pml68@users.noreply.github.com>2024-10-24 23:18:46 +0200
committerGitHub <noreply@github.com>2024-10-24 23:18:46 +0200
commitb351dd45dcd4b4c9142f069c62b51159c00922bf (patch)
treed2f24b449c3f82a9f844ce35198bad351c2ca8af /iced_drop/src/widget/operation
parentMerge pull request #1 from pml68/feat/codegen (diff)
parentfeat: implement d&d for existing elements (diff)
downloadiced-builder-b351dd45dcd4b4c9142f069c62b51159c00922bf.tar.gz
Merge pull request #2 from pml68/feat/drag-and-drop
Drag & Drop done
Diffstat (limited to 'iced_drop/src/widget/operation')
-rw-r--r--iced_drop/src/widget/operation/drop.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/iced_drop/src/widget/operation/drop.rs b/iced_drop/src/widget/operation/drop.rs
new file mode 100644
index 0000000..a76181c
--- /dev/null
+++ b/iced_drop/src/widget/operation/drop.rs
@@ -0,0 +1,90 @@
+use iced::{
+ advanced::widget::{
+ operation::{Outcome, Scrollable},
+ Id, Operation,
+ },
+ Rectangle, Vector,
+};
+
+/// Produces an [`Operation`] that will find the drop zones that pass a filter on the zone's bounds.
+/// For any drop zone to be considered, the Element must have some Id.
+/// If `options` is `None`, all drop zones will be considered.
+/// Depth determines how how deep into nested drop zones to go.
+/// If 'depth' is `None`, nested dropzones will be fully explored
+pub fn find_zones<F>(
+ filter: F,
+ options: Option<Vec<Id>>,
+ depth: Option<usize>,
+) -> impl Operation<Vec<(Id, Rectangle)>>
+where
+ F: Fn(&Rectangle) -> bool + Send + 'static,
+{
+ struct FindDropZone<F> {
+ filter: F,
+ options: Option<Vec<Id>>,
+ zones: Vec<(Id, Rectangle)>,
+ max_depth: Option<usize>,
+ c_depth: usize,
+ offset: Vector,
+ }
+
+ impl<F> Operation<Vec<(Id, Rectangle)>> for FindDropZone<F>
+ where
+ F: Fn(&Rectangle) -> bool + Send + 'static,
+ {
+ fn container(
+ &mut self,
+ id: Option<&Id>,
+ bounds: iced::Rectangle,
+ operate_on_children: &mut dyn FnMut(&mut dyn Operation<Vec<(Id, Rectangle)>>),
+ ) {
+ match id {
+ Some(id) => {
+ let is_option = match &self.options {
+ Some(options) => options.contains(id),
+ None => true,
+ };
+ let bounds = bounds - self.offset;
+ if is_option && (self.filter)(&bounds) {
+ self.c_depth += 1;
+ self.zones.push((id.clone(), bounds));
+ }
+ }
+ None => (),
+ }
+ let goto_next = match &self.max_depth {
+ Some(m_depth) => self.c_depth < *m_depth,
+ None => true,
+ };
+ if goto_next {
+ operate_on_children(self);
+ }
+ }
+
+ fn finish(&self) -> Outcome<Vec<(Id, Rectangle)>> {
+ Outcome::Some(self.zones.clone())
+ }
+
+ fn scrollable(
+ &mut self,
+ _state: &mut dyn Scrollable,
+ _id: Option<&Id>,
+ bounds: Rectangle,
+ _content_bounds: Rectangle,
+ translation: Vector,
+ ) {
+ if (self.filter)(&bounds) {
+ self.offset = self.offset + translation;
+ }
+ }
+ }
+
+ FindDropZone {
+ filter,
+ options,
+ zones: vec![],
+ max_depth: depth,
+ c_depth: 0,
+ offset: Vector { x: 0.0, y: 0.0 },
+ }
+}