dnd

package
v0.1.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package dnd provides drag and drop infrastructure for the gogpu/ui toolkit.

The package defines two optional interfaces that widgets can implement:

A Manager coordinates drag operations across the widget tree. It detects drag initiation (mouse press + 5px movement threshold), manages the active Session, and dispatches enter/over/leave/drop events to registered DropTarget widgets.

Usage

Widgets opt into drag and drop via interface implementation and type assertion:

if src, ok := w.(dnd.DragSource); ok {
    data, allow := src.DragStart(pos)
    // ...
}

The Manager handles the full lifecycle:

mgr := dnd.NewManager()
mgr.RegisterTarget(myDropZone, myDropZone.Bounds())
// In event loop:
if mgr.HandleMouseEvent(mouseEvt) {
    // event consumed by drag/drop
}

Drag Detection

Drag starts when:

  1. MousePress on a widget implementing DragSource
  2. Mouse moves more than 5px while pressed (prevents accidental drags)
  3. [DragSource.DragStart] returns true

Cancellation

An active drag can be canceled by pressing the Escape key. The Manager provides Manager.HandleKeyEvent for this purpose. Cancellation invokes [DragSource.DragEnd] with accepted=false.

Thread Safety

Manager is safe for concurrent access. All methods are protected by a mutex.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DragData

type DragData struct {
	// Kind is a type identifier for the dragged data (e.g., "text", "widget", "file").
	Kind string

	// Payload is the actual data being dragged. The concrete type depends on Kind.
	Payload any
}

DragData carries the payload during a drag operation.

Kind identifies the type of data being dragged (e.g., "text", "widget", "file"). DropTargets use Kind to determine whether they can accept the data without inspecting the payload.

type DragSource

type DragSource interface {
	// DragStart is called when a drag operation begins (after the mouse
	// moves beyond the drag threshold). It returns the drag data and
	// whether the drag should be allowed.
	DragStart(pos geometry.Point) (DragData, bool)

	// DragEnd is called when a drag operation completes. The accepted
	// parameter is true if a DropTarget accepted the data, false if the
	// drag was canceled or no target accepted it.
	DragEnd(accepted bool)
}

DragSource is implemented by widgets that can initiate drag operations.

Widgets implement this interface to participate as drag sources. The Manager detects DragSource via type assertion when processing mouse press events.

type DragVisual

type DragVisual struct {
	// CursorPos is the current cursor position during the drag.
	CursorPos geometry.Point

	// Offset is the distance from the cursor to the drag ghost's origin.
	// Typically set to the offset from the original click point within
	// the source widget.
	Offset geometry.Point

	// Effect is the current drop effect for visual feedback.
	Effect DropEffect

	// OverTarget is true when the cursor is over a valid drop target.
	OverTarget bool

	// Label is optional text to display near the cursor.
	Label string
}

DragVisual describes how to render drag feedback.

Applications can inspect the active Session and its Feedback to render custom drag visuals (ghost widgets, drop indicators, etc.). This type provides common visual parameters that painters can use.

func NewDragVisual

func NewDragVisual(session *Session) DragVisual

NewDragVisual creates a DragVisual from an active Session.

Returns a zero DragVisual if the session is nil or inactive.

type DropEffect

type DropEffect uint8

DropEffect indicates the visual feedback for a drop operation.

const (
	// DropNone indicates the target does not accept the drop.
	DropNone DropEffect = iota

	// DropCopy indicates the dragged data will be copied to the target.
	DropCopy

	// DropMove indicates the dragged data will be moved to the target.
	DropMove

	// DropLink indicates the target will create a link/reference to the data.
	DropLink
)

DropEffect constants.

func (DropEffect) String

func (e DropEffect) String() string

String returns a human-readable name for the drop effect.

type DropTarget

type DropTarget interface {
	// CanAccept returns true if this target accepts data of the given kind.
	// This is called before DragEnter to quickly filter incompatible targets.
	CanAccept(data DragData) bool

	// DragEnter is called when the drag cursor enters the target's bounds.
	DragEnter(data DragData)

	// DragOver is called while the drag cursor moves over the target.
	// Returns the DropEffect to display as visual feedback.
	DragOver(data DragData, pos geometry.Point) DropEffect

	// DragLeave is called when the drag cursor leaves the target's bounds.
	DragLeave()

	// Drop is called when the data is released over the target.
	// Returns true if the target accepted the data.
	Drop(data DragData, pos geometry.Point) bool
}

DropTarget is implemented by widgets that can accept dropped data.

Widgets implement this interface to participate as drop targets. Targets are registered with the Manager along with their bounds.

type Feedback

type Feedback struct {
	// Effect is the current drop effect at the cursor position.
	Effect DropEffect

	// Label is optional text displayed near the cursor during drag.
	Label string
}

Feedback carries visual feedback information during an active drag.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager coordinates drag and drop operations across the widget tree.

It handles the full drag lifecycle: detection (mouse press + threshold), session management, target enter/over/leave dispatch, and drop/cancel.

Manager is safe for concurrent access. All exported methods are protected by a mutex.

func NewManager

func NewManager() *Manager

NewManager creates a new drag and drop Manager.

func (*Manager) Cancel

func (m *Manager) Cancel()

Cancel cancels the active drag operation, if any.

This is equivalent to the user pressing Escape during a drag.

func (*Manager) CurrentSession

func (m *Manager) CurrentSession() *Session

CurrentSession returns the active drag session, or nil if no drag is active.

The returned Session should not be stored beyond the current event cycle, as it may be invalidated when the drag ends.

func (*Manager) HandleKeyEvent

func (m *Manager) HandleKeyEvent(evt *event.KeyEvent) bool

HandleKeyEvent processes a key event for drag cancellation.

Returns true if the event was consumed (Escape pressed during active drag).

func (*Manager) HandleMouseEvent

func (m *Manager) HandleMouseEvent(evt *event.MouseEvent, source DragSource) bool

HandleMouseEvent processes a mouse event for drag and drop.

Returns true if the event was consumed by drag/drop handling. The source parameter is the widget under the cursor for drag initiation; it may be nil if no DragSource is under the cursor.

func (*Manager) IsDragging

func (m *Manager) IsDragging() bool

IsDragging returns true if a drag operation is currently active.

func (*Manager) RegisterTarget

func (m *Manager) RegisterTarget(target DropTarget, bounds geometry.Rect)

RegisterTarget registers a DropTarget with its bounds for hit testing.

If the target is already registered, its bounds are updated.

func (*Manager) TargetCount

func (m *Manager) TargetCount() int

TargetCount returns the number of registered drop targets.

func (*Manager) UnregisterTarget

func (m *Manager) UnregisterTarget(target DropTarget)

UnregisterTarget removes a DropTarget from the manager.

If the target is currently the hover target of an active drag, DragLeave is called before removal.

func (*Manager) UpdateTargetBounds

func (m *Manager) UpdateTargetBounds(target DropTarget, bounds geometry.Rect)

UpdateTargetBounds updates the bounds for a registered target.

This should be called after layout changes to keep hit testing accurate.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session represents an active drag operation.

A Session is created by the Manager when a drag is initiated (mouse press on a DragSource followed by movement beyond the drag threshold). It tracks the drag data, source widget, positions, and current hover target.

Session is not safe for concurrent access. It is managed exclusively by the Manager, which provides its own synchronization.

func (*Session) CurrentPos

func (s *Session) CurrentPos() geometry.Point

CurrentPos returns the current cursor position during the drag.

func (*Session) CurrentTarget

func (s *Session) CurrentTarget() DropTarget

CurrentTarget returns the DropTarget currently under the cursor, or nil.

func (*Session) Data

func (s *Session) Data() DragData

Data returns the drag data for this session.

func (*Session) Feedback

func (s *Session) Feedback() Feedback

Feedback returns the current visual feedback for the drag.

func (*Session) IsActive

func (s *Session) IsActive() bool

IsActive returns true if the drag session is currently active.

func (*Session) Source

func (s *Session) Source() DragSource

Source returns the DragSource that initiated this session.

func (*Session) StartPos

func (s *Session) StartPos() geometry.Point

StartPos returns the position where the drag was initiated.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL