# iced_drop

A small library which provides a custom widget and operation to make drag and drop easier to implement in [iced](https://github.com/iced-rs/iced/tree/master)

## Easy Usage

1. For ease of use, make sure to enable the `helpers` feature which requires `iced_runtime`
- If you can't enable this feature, the process is very similar. The only difference is that you'd have to implement the helper functions `zones_on_point` and `find_zones` in `lib.rs` yourself.
- These functions convert the `find_zones` operation into an iced `Task`

2. To start implementing drag and drop functionality, first define two messages with the parameter specifications below: 
* a drop message with parameters: `iced::Point`, `iced::Rectangle`
* a handler message with parameter: `Vec<(iced::advanced::widget::Id, iced::Rectangle)>`

```rust
enum Message {
    Drop(iced::Point, iced::Rectangle),
    HandleZones(Vec<(iced::advanced::widget::Id, iced::Rectangle)>)
}
```

- The `Drop` message will be published when the left mouse button is released if the widget was being dragged (left click + mouse movement). This message provides the mouse position and layout boundaries of the droppable at the release point.
- The `HandleZones` message will be published on completion of the `iced_drop::zones_on_point` operation which finds the drop zones under the mouse position. It provides the Id and bounds for each drop zone under the given mouse position.
- The general idea is that one can use the arguments of `Drop` to feed into `zones_on_point` to get a `HandleZones` message which gives any information necessary to handle general drag-drop implementation.

3. Next, create a droppable in the view method and assign the on_drop message. The droppable function takes an `impl Into<Element>` object, so it's easy to make a droppable from any iced widget.

```rust
iced_drop::droppable("Drop me!").on_drop(Message::Drop);
```

4. Next, create a "drop zone." A drop zone is any widget that operates like a container and has some assigned Id. It's important that the widget is assigned some Id or it won't be recognized as a drop zone.

```rust
iced::widget::container("Drop zone")
    .id(iced::widget::container::Id::new("drop_zone"));
```

5. Finally, handle the update logic using the `iced_drop::zones_on_point` operation and your drop and handler messages

```rust
match message {
    Message::Drop(cursor_pos, _) => {
        return iced_drop::zones_on_point(
            Message::HandleZonesFound,
            point,
            None,
            None,
        );
    }
    Message::HandleZones(zones) => {
        println!("{:?}", zones)
    }
}
```
In this example, we only defined one zone, so the zones vector will either be empty if the droppable was not dropped on the zone, or it will contain the `drop_zone` created on step 3

## Examples

There are two examples: color, todo.

The color example is a very basic drag/drop showcase where the user can drag colors into zones and change the zone's color. I would start here.

[Link to video](https://drive.google.com/file/d/1K1CCi2Lc90IUyDufsvoUBZmUCbeg6_Fi/view?usp=sharing)

To run this examples: `cargo run -p color`

The todo example is a basic todo board application similar to Trello. This is a **MUCH** more complex example as it handles custom highlighting and nested droppable, but it just shows you can make some pretty cool things with iced.

[Link to video](https://drive.google.com/file/d/1MLOCk4Imd_oUnrTj_psbpYbwua976HmR/view?usp=sharing)

To run this example try: `cargo run -p todo`

Note: the todo example might also be a good example on how one can use operations. Check examples/todo/src/operation.rs. I didn't find any other examples of this in the iced repo except for the built-in focus operations.

## Future Development

Right now it's a little annoying having to work with iced's Id type. At some point, I will work on a drop_zone widget that can take some generic clonable type as an id, and I will create a separate find_zones operation that will return a list of this custom Id. This should make it easier to determine which drop zones were found.

## Used in the Wild

Iced is still evolving, and part of the fun is seeing how others use it. If iced_drop shows up anywhere in your work, I’d love to link it here so others can explore, learn, and connect.
