diff --git a/packages/joint-core/src/dia/CellView.mjs b/packages/joint-core/src/dia/CellView.mjs index 5caca36480..001cedb25b 100644 --- a/packages/joint-core/src/dia/CellView.mjs +++ b/packages/joint-core/src/dia/CellView.mjs @@ -498,6 +498,7 @@ export const CellView = View.extend({ linkView.notifyPointerdown(evt, x, y); linkView.eventData(evt, linkView.startArrowheadMove('target', { whenNotAllowed: 'remove' })); this.eventData(evt, { linkView }); + this.paper.setDragging(evt); }, dragLink: function(evt, x, y) { diff --git a/packages/joint-core/src/dia/ElementView.mjs b/packages/joint-core/src/dia/ElementView.mjs index 96988bb857..e5f18adc0c 100644 --- a/packages/joint-core/src/dia/ElementView.mjs +++ b/packages/joint-core/src/dia/ElementView.mjs @@ -747,6 +747,7 @@ export const ElementView = CellView.extend({ var view = this.getDelegatedView(); if (!view || !view.can('elementMove')) return; + this.paper.setDragging(evt); this.eventData(evt, { action: DragActions.MOVE, delegatedView: view diff --git a/packages/joint-core/src/dia/LinkView.mjs b/packages/joint-core/src/dia/LinkView.mjs index f23f8236fa..05c2a57a94 100644 --- a/packages/joint-core/src/dia/LinkView.mjs +++ b/packages/joint-core/src/dia/LinkView.mjs @@ -1597,6 +1597,8 @@ export const LinkView = CellView.extend({ if (this.isDefaultInteractionPrevented(evt)) return; + this.paper.setDragging(evt); + var labelNode = evt.currentTarget; var labelIdx = parseInt(labelNode.getAttribute('label-idx'), 10); @@ -1637,6 +1639,8 @@ export const LinkView = CellView.extend({ if (!this.can('arrowheadMove')) return; + this.paper.setDragging(evt); + var arrowheadNode = evt.target; var arrowheadType = arrowheadNode.getAttribute('end'); var data = this.startArrowheadMove(arrowheadType, { ignoreBackwardsCompatibility: true }); @@ -1650,6 +1654,8 @@ export const LinkView = CellView.extend({ if (!this.can('linkMove')) return; + this.paper.setDragging(evt); + this.eventData(evt, { action: 'move', dx: x, diff --git a/packages/joint-core/src/dia/Paper.mjs b/packages/joint-core/src/dia/Paper.mjs index affdcd98ad..e56898d7b7 100644 --- a/packages/joint-core/src/dia/Paper.mjs +++ b/packages/joint-core/src/dia/Paper.mjs @@ -3807,6 +3807,18 @@ export const Paper = View.extend({ this.delegateDocumentEvents(null, data); }, + // Mark `evt` as belonging to an active drag. Called from each + // action-confirmed drag-start branch (element, link, label, arrowhead, + // magnet→link). External consumers read via `isDragging(evt)`. + setDragging: function(evt) { + this.eventData(evt, { isDragging: true }); + }, + + // Returns true when a drag has been confirmed for `evt` (see `setDragging`). + isDragging: function(evt) { + return !!this.eventData(evt).isDragging; + }, + // Guard the specified event. If the event should be ignored, guard returns `true`. // Otherwise, it returns `false`. guard: function(evt, view) { diff --git a/packages/joint-core/test/jointjs/paper.js b/packages/joint-core/test/jointjs/paper.js index d35166fe7e..8e6d4d68be 100644 --- a/packages/joint-core/test/jointjs/paper.js +++ b/packages/joint-core/test/jointjs/paper.js @@ -256,6 +256,67 @@ QUnit.module('paper', function(hooks) { 'Paper area returns correct results for scaled and translated viewport.'); }); + QUnit.module('paper.setDragging() / paper.isDragging()', function() { + + QUnit.test('round-trip via the public API', function(assert) { + const data = {}; + const evt = { target: this.paper.el, type: 'mousedown', data: data }; + assert.notOk(this.paper.isDragging(evt), 'false on a fresh event'); + this.paper.setDragging(evt); + assert.ok(this.paper.isDragging(evt), 'true after setDragging'); + }); + + QUnit.test('isDragging is false until the drag-start gate passes', function(assert) { + const data = {}; + const evt = { target: this.paper.el, type: 'mousedown', data: data }; + // No drag-start has been called; data bag exists but lacks the flag. + assert.notOk(this.paper.isDragging(evt)); + // A different event keeps a clean bag. + const data2 = {}; + const evt2 = { target: this.paper.el, type: 'mousedown', data: data2 }; + assert.notOk(this.paper.isDragging(evt2)); + }); + + QUnit.test('ElementView.dragStart flips isDragging after can(\'elementMove\')', function(assert) { + const el = new joint.shapes.standard.Rectangle(); + el.resize(100, 100); + el.addTo(this.graph); + const view = el.findView(this.paper); + const data = {}; + const evt = { target: view.el, type: 'mousedown', data: data }; + assert.notOk(this.paper.isDragging(evt)); + view.pointerdown(evt, 50, 50); + assert.ok(this.paper.isDragging(evt), 'set after element pointerdown'); + }); + + QUnit.test('isDragging stays false when elementMove is denied', function(assert) { + this.paper.options.interactive = { elementMove: false }; + const el = new joint.shapes.standard.Rectangle(); + el.resize(100, 100); + el.addTo(this.graph); + const view = el.findView(this.paper); + const data = {}; + const evt = { target: view.el, type: 'mousedown', data: data }; + view.pointerdown(evt, 50, 50); + assert.notOk(this.paper.isDragging(evt), 'not set when can(elementMove) returns false'); + }); + + QUnit.test('LinkView.dragStart flips isDragging after can(\'linkMove\')', function(assert) { + const source = new joint.shapes.standard.Rectangle().resize(40, 40).position(0, 0).addTo(this.graph); + const target = new joint.shapes.standard.Rectangle().resize(40, 40).position(200, 200).addTo(this.graph); + const link = new joint.shapes.standard.Link({ + source: { id: source.id }, + target: { id: target.id } + }).addTo(this.graph); + const linkView = link.findView(this.paper); + const data = {}; + const evt = { target: linkView.el, type: 'mousedown', data: data }; + assert.notOk(this.paper.isDragging(evt)); + linkView.pointerdown(evt, 100, 100); + assert.ok(this.paper.isDragging(evt), 'set after link pointerdown'); + }); + }); + QUnit.module('paper.getRestrictedArea()', function() { QUnit.test('function', function(assert) { diff --git a/packages/joint-core/types/dia.d.ts b/packages/joint-core/types/dia.d.ts index 65884994cb..74df8a680b 100644 --- a/packages/joint-core/types/dia.d.ts +++ b/packages/joint-core/types/dia.d.ts @@ -2040,6 +2040,10 @@ export class Paper extends mvc.View { isDefined(defId: string): boolean; + setDragging(evt: Event): void; + + isDragging(evt: Event): boolean; + getComputedSize(): Size; getArea(): g.Rect;