Drag & drop
ScriptWeaver has in-application drag & drop — dragging widgets and payloads within your own windows. It comes in three layers, all built from ordinary Tk events and geometry, so it behaves the same on every platform. (This is separate from OS/file drag-and-drop — dragging a file in from the desktop.)
Each piece is a chainable widget method; pass false to turn it off.
Draggable — move a widget within its parent
.draggable() lets the user pick a widget up and move it inside its parent. The
widget becomes place-managed and follows the pointer.
const card = frame.Card({ heading: 'Notes' });
card.place.configure({ x: 20, y: 20 });
card.draggable(); // free move within the frame
card.draggable({ axis: 'x' }); // horizontal only
card.draggable({ bounds: 'none', onDrag: (e) => (status.text = `${e.x},${e.y}`) });
axis—'x','y', or'both'(default).bounds—'parent'(default, keep it inside) or'none'.handle— a child widget that starts the drag (default: the widget itself).onDragStart/onDrag/onDragEnd— each gets{ x, y, dx, dy, rootX, rootY }: the new position and the offset from the drag's start.
Drag and drop — carry a payload
Make one widget a source that carries a typed payload, and others targets
that accept it. A ghost follows the pointer; on release over an accepting target,
onDrop fires with the payload.
card.dragSource({ type: 'card', data: model });
column.dropTarget({ accept: 'card', onDrop: (e) => addTo(column, e.data) });
bin.dropTarget({ accept: ['card', 'note'], onDrop: (e) => trash(e.data) });
Acceptance is by type tag: a source declares a type, a target an accept
list (or '*' for any). onDrop fires only on a target whose accept matches
the source's type; onDragEnter / onDragOver / onDragLeave fire on any
target under the pointer (so a non-matching one can still show "no-drop"
feedback). Each event carries { source, type, data, x, y, rootX, rootY, accepted }. The payload (data) is any JSON-serializable value — usually your
model object.
Reorderable — drag to reorder a list
.reorderable() on a container lets the user drag its children into a new order.
A drop-line shows where the item will land; on drop the child moves and
onReorder fires with { from, to, child, container }.
list.reorderable({ onReorder: (e) => model.move(e.from, e.to) });
row.reorderable({ axis: 'x' });
It is layout-manager-aware: a Flex or Grid container reorders
through its live-edit API, a packed container via pack, and a place
container (absolute positions, no linear order) is a no-op. A Flex's direction
sets the default axis. Call .reorderable() again after you add or remove
children.
Try it — drag a row:
Live preview. In the Player's built-in docs viewer (
scriptweaver --help), this rendersDragReorderas a live, theme-aware widget you can interact with.
In the Designer
The same capabilities appear in the ScriptWeaver Designer's inspector as
properties — the draggable, dragSource, dropTarget, and reorderable
toggles (plus dragAxis, dragType, dropAccept, …) and the onDrag* /
onDrop / onReorder events. They are design-only: the Designer emits the
matching method calls into your app's code, so nothing drags on the design
canvas itself.
Options
The drag & drop properties as they appear in sw.reflect and the Designer
inspector. The methods above take the corresponding short names — e.g. the
dragAxis property is axis in .draggable({ axis }).
| Option | Kind | Description |
|---|---|---|
draggable |
boolean | Make the widget draggable within its parent (.draggable()). |
dragAxis |
x · y · both |
Constrain dragging to one axis. |
dragBounds |
parent · none |
Clamp the drag to the parent, or don't. |
dragSource |
boolean | Make the widget a drag source (.dragSource()). |
dragType |
string | The payload's type tag, matched against a target's dropAccept. |
dropTarget |
boolean | Make the widget a drop target (.dropTarget()). |
dropAccept |
string · list | Type tag(s) this target accepts, or * for any. |
reorderable |
boolean | Let a container's children be reordered by dragging (.reorderable()). |
reorderAxis |
x · y |
The reorder direction. |
onDragStart |
event | A drag begins (draggable widget or drag source). |
onDrag |
event | A draggable widget moves. |
onDragEnd |
event | A drag ends. |
onDragEnter |
event | A drag enters a drop target. |
onDragOver |
event | A drag moves over a drop target. |
onDragLeave |
event | A drag leaves a drop target. |
onDrop |
event | A payload is dropped on an accepting target. |
onReorder |
event | A reorder completes — { from, to, child, container }. |
See also
- Layout —
place,Flex, andGrid, which draggable and reorderable move things within. - Events & binding — the general event model these build on.