mirror of
https://github.com/google/blockly.git
synced 2026-01-26 10:10:08 +01:00
Viewport change event (#4180)
* Adding viewport ui event emitting and tests * comment out viewport ui event logic and add TODO for reference
This commit is contained in:
@@ -107,11 +107,19 @@ Blockly.ScrollbarPair.prototype.resize = function() {
|
||||
resizeV = true;
|
||||
}
|
||||
}
|
||||
if (resizeH) {
|
||||
this.hScroll.resize(hostMetrics);
|
||||
}
|
||||
if (resizeV) {
|
||||
this.vScroll.resize(hostMetrics);
|
||||
if (resizeH || resizeV) {
|
||||
try {
|
||||
Blockly.Events.disable();
|
||||
if (resizeH) {
|
||||
this.hScroll.resize(hostMetrics);
|
||||
}
|
||||
if (resizeV) {
|
||||
this.vScroll.resize(hostMetrics);
|
||||
}
|
||||
} finally {
|
||||
Blockly.Events.enable();
|
||||
}
|
||||
this.workspace_.maybeFireViewportChangeEvent();
|
||||
}
|
||||
|
||||
// Reposition the corner square.
|
||||
|
||||
@@ -323,6 +323,28 @@ Blockly.WorkspaceSvg.prototype.dragDeltaXY_ = null;
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.scale = 1;
|
||||
|
||||
// TODO(#4203) Enable viewport events after ui events refactor.
|
||||
// /**
|
||||
// * Cached scale value. Used to detect changes in viewport.
|
||||
// * @type {number}
|
||||
// * @private
|
||||
// */
|
||||
// Blockly.WorkspaceSvg.prototype.oldScale_ = 1;
|
||||
//
|
||||
// /**
|
||||
// * Cached viewport top value. Used to detect changes in viewport.
|
||||
// * @type {number}
|
||||
// * @private
|
||||
// */
|
||||
// Blockly.WorkspaceSvg.prototype.oldTop_ = 0;
|
||||
//
|
||||
// /**
|
||||
// * Cached viewport left value. Used to detect changes in viewport.
|
||||
// * @type {number}
|
||||
// * @private
|
||||
// */
|
||||
// Blockly.WorkspaceSvg.prototype.oldLeft_ = 0;
|
||||
|
||||
/**
|
||||
* The workspace's trashcan (if any).
|
||||
* @type {Blockly.Trashcan}
|
||||
@@ -1073,6 +1095,31 @@ Blockly.WorkspaceSvg.prototype.getParentSvg = function() {
|
||||
return /** @type {!SVGElement} */ (this.cachedParentSvg_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fires a viewport event if events are enabled and there is a change in
|
||||
* viewport values.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.maybeFireViewportChangeEvent = function() {
|
||||
// TODO(#4203) Enable viewport events after ui events refactor.
|
||||
// if (!Blockly.Events.isEnabled()) {
|
||||
// return;
|
||||
// }
|
||||
// var scale = this.scale;
|
||||
// var top = -this.scrollY;
|
||||
// var left = -this.scrollX;
|
||||
// if (scale == this.oldScale_ && top == this.oldTop_ && left == this.oldLeft_) {
|
||||
// return;
|
||||
// }
|
||||
// this.oldScale_ = scale;
|
||||
// this.oldTop_ = top;
|
||||
// this.oldLeft_ = left;
|
||||
// var event = new Blockly.Events.Ui(null, 'viewport', null,
|
||||
// { scale: scale, top: top, left: left });
|
||||
// event.workspaceId = this.id;
|
||||
// Blockly.Events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate this workspace to new coordinates.
|
||||
* @param {number} x Horizontal translation, in pixel units relative to the
|
||||
@@ -1097,6 +1144,8 @@ Blockly.WorkspaceSvg.prototype.translate = function(x, y) {
|
||||
if (this.grid_) {
|
||||
this.grid_.moveTo(x, y);
|
||||
}
|
||||
|
||||
this.maybeFireViewportChangeEvent();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1891,8 +1940,14 @@ Blockly.WorkspaceSvg.prototype.zoomToFit = function() {
|
||||
// Scale Units: (pixels / workspaceUnit)
|
||||
var ratioX = workspaceWidth / blocksWidth;
|
||||
var ratioY = workspaceHeight / blocksHeight;
|
||||
this.setScale(Math.min(ratioX, ratioY));
|
||||
this.scrollCenter();
|
||||
Blockly.Events.disable();
|
||||
try {
|
||||
this.setScale(Math.min(ratioX, ratioY));
|
||||
this.scrollCenter();
|
||||
} finally {
|
||||
Blockly.Events.enable();
|
||||
}
|
||||
this.maybeFireViewportChangeEvent();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -164,6 +164,212 @@ suite('WorkspaceSvg', function() {
|
||||
});
|
||||
});
|
||||
|
||||
suite.skip('Viewport change events', function() {
|
||||
function resetEventHistory(eventsFireStub, changeListenerSpy) {
|
||||
eventsFireStub.resetHistory();
|
||||
changeListenerSpy.resetHistory();
|
||||
}
|
||||
function assertSpyFiredViewportEvent(spy, workspace, expectedProperties) {
|
||||
assertEventFired(
|
||||
spy, Blockly.Events.Ui, {element: 'viewport'},
|
||||
workspace.id, null);
|
||||
assertEventFired(spy, Blockly.Events.Ui, expectedProperties,
|
||||
workspace.id, null);
|
||||
}
|
||||
function assertViewportEventFired(eventsFireStub, changeListenerSpy,
|
||||
workspace, expectedEventCount = 1) {
|
||||
var metrics = workspace.getMetrics();
|
||||
var expectedProperties = {
|
||||
element: 'viewport',
|
||||
newValue: {scale: workspace.scale, top: metrics.viewTop,
|
||||
left: metrics.viewLeft}
|
||||
};
|
||||
assertSpyFiredViewportEvent(
|
||||
eventsFireStub, workspace, expectedProperties);
|
||||
assertSpyFiredViewportEvent(
|
||||
changeListenerSpy, workspace,expectedProperties);
|
||||
sinon.assert.callCount(changeListenerSpy, expectedEventCount);
|
||||
sinon.assert.callCount(eventsFireStub, expectedEventCount);
|
||||
}
|
||||
function runViewportEventTest(eventTriggerFunc, eventsFireStub,
|
||||
changeListenerSpy, workspace, clock, expectedEventCount = 1) {
|
||||
clock.runAll();
|
||||
resetEventHistory(eventsFireStub, changeListenerSpy);
|
||||
eventTriggerFunc();
|
||||
assertViewportEventFired(
|
||||
eventsFireStub, changeListenerSpy, workspace, expectedEventCount);
|
||||
}
|
||||
setup(function() {
|
||||
defineStackBlock();
|
||||
this.changeListenerSpy = createFireChangeListenerSpy(this.workspace);
|
||||
});
|
||||
teardown(function() {
|
||||
delete Blockly.Blocks['stack_block'];
|
||||
});
|
||||
|
||||
suite('zoom', function() {
|
||||
test('setScale', function() {
|
||||
runViewportEventTest(() => this.workspace.setScale(2),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('zoom(50, 50, 1)', function() {
|
||||
runViewportEventTest(() => this.workspace.zoom(50, 50, 1),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('zoom(50, 50, -1)', function() {
|
||||
runViewportEventTest(() => this.workspace.zoom(50, 50, -1),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('zoomCenter(1)', function() {
|
||||
runViewportEventTest(() => this.workspace.zoomCenter(1),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('zoomCenter(-1)', function() {
|
||||
runViewportEventTest(() => this.workspace.zoomCenter(-1),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('zoomToFit', function() {
|
||||
var block = this.workspace.newBlock('stack_block');
|
||||
block.initSvg();
|
||||
block.render();
|
||||
runViewportEventTest(() => this.workspace.zoomToFit(),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
});
|
||||
suite('scroll', function() {
|
||||
test('centerOnBlock', function() {
|
||||
var block = this.workspace.newBlock('stack_block');
|
||||
block.initSvg();
|
||||
block.render();
|
||||
runViewportEventTest(() => this.workspace.zoomToFit(block.id),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('scroll', function() {
|
||||
runViewportEventTest(() => this.workspace.scroll(50, 50),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('scrollCenter', function() {
|
||||
runViewportEventTest(() => this.workspace.scrollCenter(),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
});
|
||||
suite('resize', function() {
|
||||
setup(function() {
|
||||
sinon.stub(Blockly, 'svgSize').callsFake((svg) => {
|
||||
return new Blockly.utils.Size(
|
||||
svg.cachedWidth_ + 10, svg.cachedHeight_ + 10);
|
||||
});
|
||||
});
|
||||
test('resize', function() {
|
||||
runViewportEventTest(() => this.workspace.resize(),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
test('resizeContents', function() {
|
||||
runViewportEventTest(() => this.workspace.resizeContents(),
|
||||
this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock);
|
||||
});
|
||||
});
|
||||
suite('Blocks triggering viewport changes', function() {
|
||||
test('block render that doesn\'t trigger scroll', function() {
|
||||
this.clock.runAll();
|
||||
resetEventHistory(this.eventsFireStub, this.changeListenerSpy);
|
||||
var block = this.workspace.newBlock('stack_block');
|
||||
block.initSvg();
|
||||
block.render();
|
||||
this.clock.runAll();
|
||||
assertEventNotFired(
|
||||
this.eventsFireStub, Blockly.Events.Ui, {element: 'viewport'});
|
||||
});
|
||||
test('block move that triggers scroll', function() {
|
||||
var block = this.workspace.newBlock('stack_block');
|
||||
block.initSvg();
|
||||
block.render();
|
||||
this.clock.runAll();
|
||||
resetEventHistory(this.eventsFireStub, this.changeListenerSpy);
|
||||
// Expect 2 events, 1 move, 1 viewport
|
||||
runViewportEventTest(() => {
|
||||
block.moveBy(1000, 1000);
|
||||
}, this.eventsFireStub, this.changeListenerSpy, this.workspace,
|
||||
this.clock, 2);
|
||||
});
|
||||
test.skip('domToWorkspace that doesn\'t trigger scroll' , function() {
|
||||
// TODO(#4192): un-skip after fixing bug with unintentional scroll.
|
||||
// 4 blocks with space in center.
|
||||
Blockly.Xml.domToWorkspace(
|
||||
Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="controls_if" x="88" y="88"></block>' +
|
||||
'<block type="controls_if" x="288" y="88"></block>' +
|
||||
'<block type="controls_if" x="88" y="238"></block>' +
|
||||
'<block type="controls_if" x="288" y="238"></block>' +
|
||||
'</xml>'),
|
||||
this.workspace);
|
||||
var xmlDom = Blockly.Xml.textToDom(
|
||||
'<block type="controls_if" x="188" y="163"></block>');
|
||||
this.clock.runAll();
|
||||
resetEventHistory(this.eventsFireStub, this.changeListenerSpy);
|
||||
// Add block in center of other blocks, not triggering scroll.
|
||||
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(
|
||||
'<block type="controls_if" x="188" y="163"></block>'), this.workspace);
|
||||
this.clock.runAll();
|
||||
assertEventNotFired(
|
||||
this.eventsFireStub, Blockly.Events.Ui, {element: 'viewport'});
|
||||
assertEventNotFired(
|
||||
this.changeListenerSpy, Blockly.Events.Ui, {element: 'viewport'});
|
||||
});
|
||||
test('domToWorkspace at 0,0 that doesn\'t trigger scroll' , function() {
|
||||
// 4 blocks with space in center.
|
||||
Blockly.Xml.domToWorkspace(
|
||||
Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="controls_if" x="-75" y="-72"></block>' +
|
||||
'<block type="controls_if" x="75" y="-72"></block>' +
|
||||
'<block type="controls_if" x="-75" y="75"></block>' +
|
||||
'<block type="controls_if" x="75" y="75"></block>' +
|
||||
'</xml>'),
|
||||
this.workspace);
|
||||
var xmlDom = Blockly.Xml.textToDom(
|
||||
'<block type="controls_if" x="0" y="0"></block>');
|
||||
this.clock.runAll();
|
||||
resetEventHistory(this.eventsFireStub, this.changeListenerSpy);
|
||||
// Add block in center of other blocks, not triggering scroll.
|
||||
Blockly.Xml.domToWorkspace(xmlDom, this.workspace);
|
||||
this.clock.runAll();
|
||||
assertEventNotFired(
|
||||
this.eventsFireStub, Blockly.Events.Ui, {element: 'viewport'});
|
||||
assertEventNotFired(
|
||||
this.changeListenerSpy, Blockly.Events.Ui, {element: 'viewport'});
|
||||
});
|
||||
test('domToWorkspace multiple blocks triggers one viewport event', function() {
|
||||
var addingMultipleBlocks = () => {
|
||||
Blockly.Xml.domToWorkspace(
|
||||
Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="controls_if" x="88" y="88"></block>' +
|
||||
'<block type="controls_if" x="288" y="88"></block>' +
|
||||
'<block type="controls_if" x="88" y="238"></block>' +
|
||||
'<block type="controls_if" x="288" y="238"></block>' +
|
||||
'</xml>'),
|
||||
this.workspace);
|
||||
};
|
||||
// Expect 10 events, 4 create, 4 move, 1 viewport, 1 finished loading
|
||||
runViewportEventTest(addingMultipleBlocks, this.eventsFireStub,
|
||||
this.changeListenerSpy, this.workspace, this.clock, 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Workspace Base class', function() {
|
||||
testAWorkspace();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user