Skip to content

Commit

Permalink
fix(context-pad): only update visibility once per frame
Browse files Browse the repository at this point in the history
  • Loading branch information
marstamm committed Jun 5, 2024
1 parent 1ed8694 commit 58350ab
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 11 deletions.
44 changes: 33 additions & 11 deletions lib/features/context-pad/ContextPad.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export default function ContextPad(canvas, elementRegistry, eventBus) {
this._elementRegistry = elementRegistry;
this._eventBus = eventBus;

this._requestedFrame = null;

this._current = null;

this._init();
Expand Down Expand Up @@ -140,6 +142,12 @@ ContextPad.prototype._init = function() {
self._updateVisibility();
});

this._eventBus.on('diagram.destroy', function() {
if (self._requestedFrame) {
window.cancelAnimationFrame(self._requestedFrame);
}
});

this._container = this._createContainer();
};

Expand Down Expand Up @@ -622,25 +630,39 @@ ContextPad.prototype._updatePosition = function() {
* using the `djs-element-hidden` or `djs-label-hidden` markers.
*/
ContextPad.prototype._updateVisibility = function() {
if (!this.isOpen()) {

// Only update pad once per frame
// cf. https://github.com/camunda/camunda-modeler/issues/4335
if (this._requestedFrame) {
return;
}

var self = this;
// schedule update for next frame
this._requestedFrame = window.requestAnimationFrame(() => {
this._requestedFrame = null;

if (!this.isOpen()) {
return;
}

var target = this._current.target;
var self = this;

var targets = isArray(target) ? target : [ target ];
var target = this._current.target;

var targets = isArray(target) ? target : [ target ];

var isHidden = targets.some(function(target) {
return self._canvas.hasMarker(target, MARKER_HIDDEN);
});

if (isHidden) {
self.hide();
} else {
self.show();
}

var isHidden = targets.some(function(target) {
return self._canvas.hasMarker(target, MARKER_HIDDEN);
});

if (isHidden) {
self.hide();
} else {
self.show();
}
};

/**
Expand Down
71 changes: 71 additions & 0 deletions test/spec/features/context-pad/ContextPadSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,17 @@ describe('features/context-pad', function() {

describe('<element.marker.update>', function() {

var clock;

beforeEach(function() {
clock = sinon.useFakeTimers();
});

afterEach(function() {
clock.restore();
});


it('should hide context pad when djs-element-hidden is added', inject(function(canvas, contextPad) {

// given
Expand All @@ -942,11 +953,13 @@ describe('features/context-pad', function() {

contextPad.open(shape);

// assume
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.true;

// when
canvas.addMarker(shape, 'djs-element-hidden');
clock.runToFrame();

// then
expect(contextPad.isOpen()).to.be.true;
Expand All @@ -964,18 +977,76 @@ describe('features/context-pad', function() {
canvas.addMarker(shape, 'djs-element-hidden');

contextPad.open(shape);
clock.runToFrame();

// assume
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.false;

// when
canvas.removeMarker(shape, 'djs-element-hidden');
clock.runToFrame();

// then
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.true;
}));


it('should only update once per frame', inject(function(canvas, contextPad) {

// given
var hideSpy = sinon.spy(contextPad, 'hide');
var shape = { id: 's1', width: 100, height: 100, x: 10, y: 10 };

canvas.addShape(shape);

contextPad.open(shape);


// assume
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.true;

// when
canvas.addMarker(shape, 'djs-element-hidden');
canvas.removeMarker(shape, 'djs-element-hidden');
canvas.addMarker(shape, 'djs-element-hidden');

clock.runToFrame();

// then
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.false;
expect(hideSpy).to.have.been.calledOnce;
}));


it('should not update when diagram was destroyed', inject(function(canvas, contextPad) {

// given
var diagramJs = getDiagramJS();
var hideSpy = sinon.spy(contextPad, 'hide');

var shape = { id: 's1', width: 100, height: 100, x: 10, y: 10 };

canvas.addShape(shape);

contextPad.open(shape);

// assume
expect(contextPad.isOpen()).to.be.true;
expect(contextPad.isShown()).to.be.true;

// when
canvas.addMarker(shape, 'djs-element-hidden');
diagramJs.destroy();

clock.runToFrame();

// then
expect(hideSpy).not.to.have.been.called;
}));
});

});
Expand Down

0 comments on commit 58350ab

Please sign in to comment.