Function re_viewer::external::re_ui::drag_and_drop::find_drop_target

source ·
pub fn find_drop_target<ItemId>(
    ui: &Ui,
    item_context: &ItemContext<ItemId>,
    item_rect: Rect,
    body_rect: Option<Rect>,
    item_height: f32
) -> Option<DropTarget<ItemId>>
where ItemId: Copy,
Expand description

Compute the geometry of the drag cursor and where the dragged item should be inserted.

This function performs the following tasks:

  • based on item_rect and body_rect, establish the geometry of actual drop zones (see below)
  • test the mouse cursor against these zones
  • if one is a match:
    • compute the geometry of a drop insertion indicator
    • use the context provided in item_context to return the “logical” drop target (ie. the target container and position within it)

This function implements the following logic:


                       insert         insert last in container before me
                     before me           (if any) or insert before me
                         │                             │
                     ╔═══▼═════════════════════════════▼══════════════════╗
                     ║      │                                             ║
        leaf item    ║ ─────┴──────────────────────────────────────────── ║
                     ║                                                    ║
                     ╚═════════════════════▲══════════════════════════════╝
                                           │
                                    insert after me


                       insert         insert last in container before me
                     before me           (if any) or insert before me
                         │                             │
                     ╔═══▼═════════════════════════════▼══════════════════╗
        leaf item    ║      │                                             ║
        with body    ║ ─────┴──────────────────────────────────────────── ║
                     ║                                                    ║
                     ╚══════╦══════════════════════════════════════▲══════╣ ─┐
                     │      ║                                      │      ║  │
                     │      ║                                   insert    ║  │
                     │      ║                                  after me   ║  │
                     │      ╠══                                         ══╣  │
                     │      ║             no insertion possible           ║  │
                     │      ║             here by definition of           ║  │ body
                     │      ║              parent being a leaf            ║  │
                     │      ╠══                                         ══╣  │
                     │      ║                                             ║  │
                     │      ║                                             ║  │
                     │      ║                                             ║  │
                     └──▲── ╚══════════════════════════▲══════════════════╝ ─┘
                        │                              │
                     insert                         insert
                    after me                       after me


                       insert         insert last in container before me
                     before me           (if any) or insert before me
                         │                             │
                     ╔═══▼═════════════════════════════▼══════════════════╗
   container item    ║      │                                             ║
 (empty/collapsed    ║ ─────┼──────────────────────────────────────────── ║
            body)    ║      │                                             ║
                     ╚═══▲═════════════════════════════▲══════════════════╝
                         │                             │
                      insert                   insert inside me
                     after me                     at pos = 0


                       insert         insert last in container before me
                     before me           (if any) or insert before me
                         │                             │
                     ╔═══▼═════════════════════════════▼══════════════════╗
   container item    ║      │                                             ║
        with body    ║ ─────┴──────────────────────────────────────────── ║
                     ║                                                    ║
                     ╚═▲════╦═════════════════════════════════════════════╣ ─┐
                       │    ║                                             ║  │
                    insert  ║                                             ║  │
                 inside me  ║                                             ║  │
                at pos = 0  ╠══                                         ══╣  │
                            ║                  same logic                 ║  │
                            ║                 recursively                 ║  │ body
                    insert  ║                 applied here                ║  │
                  after me  ╠══                                         ══╣  │
                       │    ║                                             ║  │
                     ┌─▼─── ║                                             ║  │
                     │      ║                                             ║  │
                     └───── ╚═════════════════════════════════════════════╝ ─┘

                                             not a valid drop zone
                                                       │
                     ╔═════════════════════════════════▼══════════════════╗
   root container    ║                                                    ║
             item    ║ ────────────────────────────────────────────────── ║
                     ║                                                    ║
                     ╚════════════════════════▲═══════════════════════════╝
                                              │
                                      insert inside me
                                         at pos = 0

Here are a few observations of the above that help navigate the “if-statement-of-death” in the implementation:

  • The top parts of the item are treated the same in most cases (root container is an exception).
  • Handling of the body can be simplified by making the sensitive area either a small corner (container case), or the entire body (leaf case). Then, that area always maps to “insert after me”.
  • The bottom parts have the most difference between cases and need case-by-case handling. In both leaf item cases, the entire bottom part maps to “insert after me”, though.

Note: in debug builds, press Alt to visualize the drag zones while dragging.