From c9744168ba203c564d46c443b932b4b5a60e3c60 Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko <2277098+anoshenko@users.noreply.github.com> Date: Sat, 7 Jun 2025 12:19:17 +0300 Subject: [PATCH] Added "drag effect" property --- app_scripts.js | 5 +++ dragAndDrop.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++--- propertySet.go | 5 +++ view.go | 10 ++++-- 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/app_scripts.js b/app_scripts.js index 13f2c88..c729388 100644 --- a/app_scripts.js +++ b/app_scripts.js @@ -2193,6 +2193,11 @@ function dragStartEvent(element, event) { let img = new Image(); img.src = image; event.dataTransfer.setDragImage(img, x, y); + + let effect = element.getAttribute("data-drag-effect"); + if (effect) { + event.dataTransfer.effectAllowed = effect; + } } // TODO drag effect diff --git a/dragAndDrop.go b/dragAndDrop.go index 579017f..8a0c5e4 100644 --- a/dragAndDrop.go +++ b/dragAndDrop.go @@ -2,6 +2,7 @@ package rui import ( "encoding/base64" + "fmt" "maps" "strings" ) @@ -38,6 +39,29 @@ const ( // Supported types: float, int, string. DragImageYOffset PropertyName = "drag-image-y-offset" + // DragEffect is the constant for "drag-effect" property tag. + // + // Used by View. + // Specifies the effect that is allowed for a drag operation. + // The copy operation is used to indicate that the data being dragged will be copied + // from its present location to the drop location. + // The move operation is used to indicate that the data being dragged will be moved, + // and the link operation is used to indicate that some form of relationship + // or connection will be created between the source and drop locations. + // + // Supported types: int, string. + // + // Values: + // - 0 (DragEffectAll) or "all" - All operations are permitted (defaut value). + // - 1 (DragEffectCopy) or "copy" - A copy of the source item may be made at the new location. + // - 2 (DragEffectMove) or "move" - An item may be moved to a new location. + // - 3 (DragEffectLink) or "link" - A link may be established to the source at the new location. + // - 4 (DragEffectCopyMove) or "copyMove" - A copy or move operation is permitted. + // - 5 (DragEffectCopyLink) or "copyLink" - A copy or link operation is permitted. + // - 6 (DragEffectLinkMove) or "linkMove" - A link or move operation is permitted. + // - 7 (DragEffectNone) or "none" - The item may not be dropped. + DragEffect PropertyName = "drag-effect" + // DragStartEvent is the constant for "drag-start-event" property tag. // // Used by View. @@ -91,6 +115,30 @@ const ( // General listener format: // DropEvent PropertyName = "drop-event" + + // DragEffectAll - the value of the "drag-effect" property: all operations (copy, move, and link) are permitted (defaut value). + DragEffectAll = 0 + + // DragEffectCopy - the value of the "drag-effect" property: a copy of the source item may be made at the new location. + DragEffectCopy = 1 + + // DragEffectMove - the value of the "drag-effect" property: an item may be moved to a new location. + DragEffectMove = 2 + + // DragEffectLink - the value of the "drag-effect" property: a link may be established to the source at the new location. + DragEffectLink = 3 + + // DragEffectCopyMove - the value of the "drag-effect" property: a copy or move operation is permitted. + DragEffectCopyMove = 4 + + // DragEffectCopyLink - the value of the "drag-effect" property: a copy or link operation is permitted. + DragEffectCopyLink = 5 + + // DragEffectLinkMove - the value of the "drag-effect" property: a link or move operation is permitted. + DragEffectLinkMove = 6 + + // DragEffectNone - the value of the "drag-effect" property: the item may not be dropped. + DragEffectNone = 7 ) // MouseEvent represent a mouse event @@ -197,15 +245,22 @@ func dragAndDropHtml(view View, buffer *strings.Builder) { } } - if f, ok := floatTextProperty(view, DragImageXOffset, session, 0); ok { + if f := GetDragImageXOffset(view); f != 0 { buffer.WriteString(` data-drag-image-x="`) - buffer.WriteString(f) + buffer.WriteString(fmt.Sprintf("%g", f)) buffer.WriteString(`" `) } - if f, ok := floatTextProperty(view, DragImageYOffset, session, 0); ok { + if f := GetDragImageYOffset(view); f != 0 { buffer.WriteString(` data-drag-image-y="`) - buffer.WriteString(f) + buffer.WriteString(fmt.Sprintf("%g", f)) + buffer.WriteString(`" `) + } + + effects := enumProperties[DragEffect].cssValues + if n := GetDragEffect(view); n > 0 && n < len(effects) { + buffer.WriteString(` data-drag-effect="`) + buffer.WriteString(effects[n]) buffer.WriteString(`" `) } } @@ -258,3 +313,34 @@ func GetDragData(view View, subviewID ...string) map[string]string { return result } + +// GetDragImageXOffset returns the horizontal offset in pixels within the drag feedback image.. +// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned. +func GetDragImageXOffset(view View, subviewID ...string) float64 { + return floatStyledProperty(view, subviewID, DragImageXOffset, 0) +} + +// GetDragImageYOffset returns the vertical offset in pixels within the drag feedback image.. +// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned. +func GetDragImageYOffset(view View, subviewID ...string) float64 { + return floatStyledProperty(view, subviewID, DragImageYOffset, 0) +} + +// GetDragEffect returns the effect that is allowed for a drag operation. +// The copy operation is used to indicate that the data being dragged will be copied from its present location to the drop location. +// The move operation is used to indicate that the data being dragged will be moved, +// and the link operation is used to indicate that some form of relationship +// or connection will be created between the source and drop locations.. Returns one of next values: +// - 0 (DragEffectAll) or "all" - All operations are permitted (defaut value). +// - 1 (DragEffectCopy) or "copy" - A copy of the source item may be made at the new location. +// - 2 (DragEffectMove) or "move" - An item may be moved to a new location. +// - 3 (DragEffectLink) or "link" - A link may be established to the source at the new location. +// - 4 (DragEffectCopyMove) or "copyMove" - A copy or move operation is permitted. +// - 5 (DragEffectCopyLink) or "copyLink" - A copy or link operation is permitted. +// - 6 (DragEffectLinkMove) or "linkMove" - A link or move operation is permitted. +// - 7 (DragEffectNone) or "none" - The item may not be dropped. +// +// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned. +func GetDragEffect(view View, subviewID ...string) int { + return enumStyledProperty(view, subviewID, DragEffect, DragEffectAll, true) +} diff --git a/propertySet.go b/propertySet.go index c788382..a6eec7d 100644 --- a/propertySet.go +++ b/propertySet.go @@ -496,6 +496,11 @@ var enumProperties = map[PropertyName]enumPropertyData{ string(ColumnFill), []string{"balance", "auto"}, }, + DragEffect: { + []string{"all", "copy", "move", "link", "copyMove", "copyLink", "linkMove", "none"}, + "", + []string{"all", "copy", "move", "link", "copyMove", "copyLink", "linkMove", "none"}, + }, } func notCompatibleType(tag PropertyName, value any) { diff --git a/view.go b/view.go index 2a46471..8adfbe1 100644 --- a/view.go +++ b/view.go @@ -866,19 +866,25 @@ func (view *viewData) propertyChanged(tag PropertyName) { } case DragImageXOffset: - if f, ok := floatTextProperty(view, DragImageXOffset, session, 0); ok { + if f := GetDragImageXOffset(view); f != 0 { session.updateProperty(htmlID, "data-drag-image-x", f) } else { session.removeProperty(view.htmlID(), "data-drag-image-x") } case DragImageYOffset: - if f, ok := floatTextProperty(view, DragImageYOffset, session, 0); ok { + if f := GetDragImageXOffset(view); f != 0 { session.updateProperty(htmlID, "data-drag-image-y", f) } else { session.removeProperty(view.htmlID(), "data-drag-image-y") } + case DragEffect: + effects := enumProperties[DragEffect].cssValues + if n := GetDragEffect(view); n > 0 && n < len(effects) { + session.updateProperty(htmlID, "data-drag-effect", effects[n]) + } + case DataList: updateInnerHTML(view.htmlID(), view.Session())