Files
gio/io/transfer/transfer.go
T
Pierre Curto 03016f0c69 widget: add drag and drop support
This patch adds internal Drag and Drop support to app.Windows.

The new package io/transfer adds the ability to
define draggable and droppable targets, which
are leveraged by the new widget.Draggable type.

The API is generic and could handle future use
cases, such as external Drag and Drop.

Updates gio#153

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-12-07 12:45:53 +01:00

110 lines
3.3 KiB
Go

// Package transfer contains operations and events for brokering data transfers.
//
// The transfer protocol is as follows:
//
// - Data sources are registered with SourceOps, data targets with TargetOps.
// - A data source receives a RequestEvent when a transfer is initiated.
// It must respond with an OfferOp.
// - The target receives a DataEvent when transferring to it. It must close
// the event data after use.
//
// When a user initiates a pointer-guided drag and drop transfer, the
// source as well as all potential targets receive an InitiateEvent.
// Potential targets are targets with at least one MIME type in common
// with the source. When a drag gesture completes, a CancelEvent is sent
// to the source and all potential targets.
//
// Note that the RequestEvent is sent to the source upon drop.
package transfer
import (
"io"
"gioui.org/internal/ops"
"gioui.org/io/event"
"gioui.org/op"
)
// SourceOp registers a tag as a data source for a MIME type.
// Use multiple SourceOps if a tag supports multiple types.
type SourceOp struct {
Tag event.Tag
// Type is the MIME type supported by this source.
Type string
}
// TargetOp registers a tag as a data target.
// Use multiple TargetOps if a tag supports multiple types.
type TargetOp struct {
Tag event.Tag
// Type is the MIME type accepted by this target.
Type string
}
// OfferOp is used by data sources as a response to a RequestEvent.
type OfferOp struct {
Tag event.Tag
// Type is the MIME type of Data.
// It must be the Type from the corresponding RequestEvent.
Type string
// Data contains the offered data. It is closed when the
// transfer is complete or cancelled.
// Data must be kept valid until closed, and it may be used from
// a goroutine separate from the one processing the frame..
Data io.ReadCloser
}
func (op SourceOp) Add(o *op.Ops) {
data := ops.Write2(&o.Internal, ops.TypeSourceLen, op.Tag, op.Type)
data[0] = byte(ops.TypeSource)
}
func (op TargetOp) Add(o *op.Ops) {
data := ops.Write2(&o.Internal, ops.TypeTargetLen, op.Tag, op.Type)
data[0] = byte(ops.TypeTarget)
}
// Add the offer to the list of operations.
// It panics if the Data field is not set.
func (op OfferOp) Add(o *op.Ops) {
if op.Data == nil {
panic("invalid nil data in OfferOp")
}
data := ops.Write3(&o.Internal, ops.TypeOfferLen, op.Tag, op.Type, op.Data)
data[0] = byte(ops.TypeOffer)
}
// RequestEvent requests data from a data source. The source must
// respond with an OfferOp.
type RequestEvent struct {
// Type is the first matched type between the source and the target.
Type string
}
func (RequestEvent) ImplementsEvent() {}
// InitiateEvent is sent to a data source when a drag-and-drop
// transfer gesture is initiated.
//
// Potential data targets also receive the event.
type InitiateEvent struct{}
func (InitiateEvent) ImplementsEvent() {}
// CancelEvent is sent to data sources and targets to cancel the
// effects of an InitiateEvent.
type CancelEvent struct{}
func (CancelEvent) ImplementsEvent() {}
// DataEvent is sent to the target receiving the transfer.
type DataEvent struct {
// Type is the MIME type of Data.
Type string
// Open returns the transfer data. It is only valid to call Open in the frame
// the DataEvent is received. The caller must close the return value after use.
Open func() io.ReadCloser
}
func (DataEvent) ImplementsEvent() {}