Skip to content

Design revised IDraggable / IDragStrategy API #739

@cpcallen

Description

@cpcallen

Tracking bug for work I (@cpcallen) am doing in creating a revised version of the IDraggable/IDragStrategy API.

Proposal

I propose that we revise the IDraggable / IDragStrategy API—or, IMHO preferably, supplant them with a new API IMovable / IMoveStrategy)—with the following characteristics:

  • The API methods' parameters are extensible, so that a custom dragger can pass arbitrary extra information to a custom drag strategy.
  • It's possible to indicate whether or a stack heal and/or a row heal should occur at drag start.
  • It's possible to indicate whether a move indicator bubble should be shown.
  • Each step in a move can be specified in terms of:
    • absolute position in workspace coordinates (not strictly needed, but seems like it should be possible?)
    • total delta in workspace coordinates (needed for drags)
    • incremental delta in workspace coordinates (needed for unconstrained moves), or
    • by a step to the next drag target or candidate connection in a particular logical direction (needed for constrained moves)
      • where the set of logical direction is extensible, but includes next/previous/next-line/previous-line.
  • It's possible to request that a move be aborted.
  • It's possible to arrange for an aborted move to result in the deletion of the draggable (needed for aborting insert of new blocks).
  • It's possible to arrange to show a hint when an attempted constrained moves result in no actual movement.
  • It should be possible to specify a hotpoint in screen coordinates, representing the location of the pointer, to check against IDragTargets.
  • The dragStart method (or equivalent) should provide some way to report what IDraggable is actually being dragged.
    • This is to allow API clients to detect e.g. that dragging a shadow block actually moves its parent, or duplicate-on-drag parameter blocks.

Further, API implementations will be fully responsible for:

  • Computing physical move distance for logical moves.
  • Handling interactions with IDragTargets (and, for Blocks, candidate connections).
  • Generate events and grouping them correctly.

Notes and queries

  • For delete-on-abort, we could use a single special-purpose flag, but maybe an end-of-move callback would be better: this would allow the API client to do other things such as ensuring that focus is restored the correct location when a move finishes, which might depend on state information well outside the domain of the draggable.
  • Similarly, for showing hints we could use flag or provide a more general way to detect whether an attempted move has succeeded.
  • Need to consider best approach for testing against drag targets when doing keyboard moves, where we don't have an (actual) pointer location.
    • Note that this currently depends on Dragger.prototype.wouldDeleteDraggable calling WorkspaceSvg.prototype.getDragTarget, which takes a PointerEvent rather than just screen coordinates.
  • Do we want to be able to specify a move in terms of a drag target or connection candidate? It would be handy to be able to specify the initial connection candidate at drag start time when inserting new blocks onto the workspace, though equally the new block could just be attached to that connection and then an ordinary move started.
  • Duplicate-on-drag is notionally very similar to drag-from-flyout, but in practice they are different:
    • Drag-from-flyout duplicates the block before drag start, and the gesture knows its the duplicate being dragged.
    • Duplicate-on-drag duplicates the block at drag start, and the gesture believes it is the original being dragged.
      • Scratch blocks fixes this by having DuplicateonDragDraggable.prototype.drag call dragger.setDraggable(this.copy) to inform it of the unexpected change of plans.
  • Should we include a UIEvent in the options object? The goal of the options object is to subsume the things that existing drag strategies use the e: PointerEvent parameter for, so that they can be done in an input-device-agnostic way, so the intention is that the UIEvent not be used by the core drag strategies—but it might maximise flexibility for developers.
  • Can we pick just one of absolute / total delta / incremental delta?
    • If there was an easy way to get absolute xy position then absolute would suffice.
    • We could avoid the need for total delta by requiring the caller to to compute incremental offsets (by comparing current position, which need not be absolute, to inital position).
      • But is there a risk of getting out of sync?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions