mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-10 21:18:53 -04:00
Decompose functions in flyout. Does not change behaviour.
This commit is contained in:
parent
52eb6adcc2
commit
c8f98a7ded
1 changed files with 156 additions and 94 deletions
250
core/flyout.js
250
core/flyout.js
|
@ -264,20 +264,8 @@ Blockly.Flyout.prototype.position = function() {
|
|||
if (this.RTL) {
|
||||
edgeWidth *= -1;
|
||||
}
|
||||
var path = ['M ' + (this.RTL ? this.width_ : 0) + ',0'];
|
||||
path.push('h', edgeWidth);
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
this.RTL ? 0 : 1,
|
||||
this.RTL ? -this.CORNER_RADIUS : this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
path.push('v', Math.max(0, metrics.viewHeight - this.CORNER_RADIUS * 2));
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
this.RTL ? 0 : 1,
|
||||
this.RTL ? this.CORNER_RADIUS : -this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
path.push('h', -edgeWidth);
|
||||
path.push('z');
|
||||
this.svgBackground_.setAttribute('d', path.join(' '));
|
||||
|
||||
this.setBackgroundPath_(edgeWidth, metrics.viewHeight);
|
||||
|
||||
var x = metrics.absoluteLeft;
|
||||
if (this.RTL) {
|
||||
|
@ -296,6 +284,37 @@ Blockly.Flyout.prototype.position = function() {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and set the path for the visible boundaries of the flyout.
|
||||
* @param {number} width The width of the flyout, not including the
|
||||
* rounded corners.
|
||||
* @param {number} height The height of the flyout, not including
|
||||
* rounded corners.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
var path = ['M ' + (this.RTL ? this.width_ : 0) + ',0'];
|
||||
// Top.
|
||||
path.push('h', width);
|
||||
// Rounded corner.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
this.RTL ? 0 : 1,
|
||||
this.RTL ? -this.CORNER_RADIUS : this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
// Side closest to the workspace.
|
||||
path.push('v', Math.max(0, height - this.CORNER_RADIUS * 2));
|
||||
// Rounded corner.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
this.RTL ? 0 : 1,
|
||||
this.RTL ? this.CORNER_RADIUS : -this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
// Bottom.
|
||||
path.push('h', -width);
|
||||
// Side away from the workspace.
|
||||
path.push('z');
|
||||
this.svgBackground_.setAttribute('d', path.join(' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* Scroll the flyout to the top.
|
||||
*/
|
||||
|
@ -363,18 +382,7 @@ Blockly.Flyout.prototype.hide = function() {
|
|||
*/
|
||||
Blockly.Flyout.prototype.show = function(xmlList) {
|
||||
this.hide();
|
||||
// Delete any blocks from a previous showing.
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
if (block.workspace == this.workspace_) {
|
||||
block.dispose(false, false);
|
||||
}
|
||||
}
|
||||
// Delete any background buttons from a previous showing.
|
||||
for (var i = 0, rect; rect = this.buttons_[i]; i++) {
|
||||
goog.dom.removeNode(rect);
|
||||
}
|
||||
this.buttons_.length = 0;
|
||||
this.clearOldBlocks_();
|
||||
|
||||
if (xmlList == Blockly.Variables.NAME_TYPE) {
|
||||
// Special category for variables.
|
||||
|
@ -406,6 +414,38 @@ Blockly.Flyout.prototype.show = function(xmlList) {
|
|||
}
|
||||
}
|
||||
|
||||
this.layoutBlocks_(blocks, gaps, margin);
|
||||
|
||||
// IE 11 is an incompetant browser that fails to fire mouseout events.
|
||||
// When the mouse is over the background, deselect all blocks.
|
||||
var deselectAll = function(e) {
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
block.removeSelect();
|
||||
}
|
||||
};
|
||||
this.listeners_.push(Blockly.bindEvent_(this.svgBackground_, 'mouseover',
|
||||
this, deselectAll));
|
||||
|
||||
this.width_ = 0;
|
||||
this.reflow();
|
||||
|
||||
this.filterForCapacity_();
|
||||
|
||||
// Fire a resize event to update the flyout's scrollbar.
|
||||
Blockly.fireUiEventNow(window, 'resize');
|
||||
this.reflowWrapper_ = this.reflow.bind(this);
|
||||
this.workspace_.addChangeListener(this.reflowWrapper_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Lay out the blocks in the flyout.
|
||||
* @param {!Array<Blockly.BlockSvg>} blocks The blocks to lay out.
|
||||
* @param {!Array<number>} gaps The visible gaps between blocks.
|
||||
* @param {number} margin The margin around the edges of the flyout.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.layoutBlocks_ = function(blocks, gaps, margin) {
|
||||
// Lay out the blocks vertically.
|
||||
var cursorY = margin;
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
|
@ -434,47 +474,57 @@ Blockly.Flyout.prototype.show = function(xmlList) {
|
|||
block.flyoutRect_ = rect;
|
||||
this.buttons_[i] = rect;
|
||||
|
||||
if (this.autoClose) {
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,
|
||||
this.createBlockFunc_(block)));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null,
|
||||
this.createBlockFunc_(block)));
|
||||
} else {
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,
|
||||
this.blockMouseDown_(block)));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null,
|
||||
this.blockMouseDown_(block)));
|
||||
}
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block,
|
||||
block.addSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block,
|
||||
block.removeSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block,
|
||||
block.addSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block,
|
||||
block.removeSelect));
|
||||
this.addBlockListeners_(root, block, rect);
|
||||
}
|
||||
};
|
||||
|
||||
// IE 11 is an incompetant browser that fails to fire mouseout events.
|
||||
// When the mouse is over the background, deselect all blocks.
|
||||
var deselectAll = function(e) {
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
block.removeSelect();
|
||||
/**
|
||||
* Delete blocks and background buttons from a previous showing of the flyout.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.clearOldBlocks_ = function() {
|
||||
// Delete any blocks from a previous showing.
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
if (block.workspace == this.workspace_) {
|
||||
block.dispose(false, false);
|
||||
}
|
||||
};
|
||||
this.listeners_.push(Blockly.bindEvent_(this.svgBackground_, 'mouseover',
|
||||
this, deselectAll));
|
||||
}
|
||||
// Delete any background buttons from a previous showing.
|
||||
for (var j = 0, rect; rect = this.buttons_[j]; j++) {
|
||||
goog.dom.removeNode(rect);
|
||||
}
|
||||
this.buttons_.length = 0;
|
||||
};
|
||||
|
||||
this.width_ = 0;
|
||||
this.reflow();
|
||||
|
||||
this.filterForCapacity_();
|
||||
|
||||
// Fire a resize event to update the flyout's scrollbar.
|
||||
Blockly.fireUiEventNow(window, 'resize');
|
||||
this.reflowWrapper_ = this.reflow.bind(this);
|
||||
this.workspace_.addChangeListener(this.reflowWrapper_);
|
||||
/**
|
||||
* Add listeners to a block that has been added to the flyout.
|
||||
* @param {!Element} root The root node of the SVG group the block is in.
|
||||
* @param {!Blockly.Block} block The block to add listeners for.
|
||||
* @param {!Element} rect The invisible rectangle under the block that acts as
|
||||
* a button for that block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) {
|
||||
if (this.autoClose) {
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,
|
||||
this.createBlockFunc_(block)));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null,
|
||||
this.createBlockFunc_(block)));
|
||||
} else {
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,
|
||||
this.blockMouseDown_(block)));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null,
|
||||
this.blockMouseDown_(block)));
|
||||
}
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block,
|
||||
block.addSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block,
|
||||
block.removeSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block,
|
||||
block.addSelect));
|
||||
this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block,
|
||||
block.removeSelect));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -656,37 +706,7 @@ Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) {
|
|||
return;
|
||||
}
|
||||
Blockly.Events.disable();
|
||||
// Create the new block by cloning the block in the flyout (via XML).
|
||||
var xml = Blockly.Xml.blockToDom(originBlock);
|
||||
var block = Blockly.Xml.domToBlock(xml, workspace);
|
||||
// Place it in the same spot as the flyout copy.
|
||||
var svgRootOld = originBlock.getSvgRoot();
|
||||
if (!svgRootOld) {
|
||||
throw 'originBlock is not rendered.';
|
||||
}
|
||||
var xyOld = Blockly.getSvgXY_(svgRootOld, workspace);
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
if (flyout.RTL) {
|
||||
var width = workspace.getMetrics().viewWidth - flyout.width_;
|
||||
xyOld.x += width / workspace.scale - width;
|
||||
} else {
|
||||
xyOld.x += flyout.workspace_.scrollX / flyout.workspace_.scale -
|
||||
flyout.workspace_.scrollX;
|
||||
}
|
||||
xyOld.y += flyout.workspace_.scrollY / flyout.workspace_.scale -
|
||||
flyout.workspace_.scrollY;
|
||||
var svgRootNew = block.getSvgRoot();
|
||||
if (!svgRootNew) {
|
||||
throw 'block is not rendered.';
|
||||
}
|
||||
var xyNew = Blockly.getSvgXY_(svgRootNew, workspace);
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
xyNew.x += workspace.scrollX / workspace.scale - workspace.scrollX;
|
||||
xyNew.y += workspace.scrollY / workspace.scale - workspace.scrollY;
|
||||
if (workspace.toolbox_ && !workspace.scrollbar) {
|
||||
xyNew.x += workspace.toolbox_.width / workspace.scale;
|
||||
}
|
||||
block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);
|
||||
var block = flyout.placeNewBlock_(originBlock, workspace);
|
||||
Blockly.Events.enable();
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
Blockly.Events.setGroup(true);
|
||||
|
@ -704,6 +724,48 @@ Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a block from the flyout to the workspace and position it correctly.
|
||||
* @param {!Blockly.Block} originBlock The flyout block to copy.
|
||||
* @param {!Blockly.Workspace} workspace The main workspace.
|
||||
* @return {!Blockly.Block} The new block in the main workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.placeNewBlock_ = function(originBlock, workspace) {
|
||||
// Create the new block by cloning the block in the flyout (via XML).
|
||||
var xml = Blockly.Xml.blockToDom(originBlock);
|
||||
var block = Blockly.Xml.domToBlock(xml, workspace);
|
||||
// Place it in the same spot as the flyout copy.
|
||||
var svgRootOld = originBlock.getSvgRoot();
|
||||
if (!svgRootOld) {
|
||||
throw 'originBlock is not rendered.';
|
||||
}
|
||||
var xyOld = Blockly.getSvgXY_(svgRootOld, workspace);
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
if (this.RTL) {
|
||||
var width = workspace.getMetrics().viewWidth - this.width_;
|
||||
xyOld.x += width / workspace.scale - width;
|
||||
} else {
|
||||
xyOld.x += this.workspace_.scrollX / this.workspace_.scale -
|
||||
this.workspace_.scrollX;
|
||||
}
|
||||
xyOld.y += this.workspace_.scrollY / this.workspace_.scale -
|
||||
this.workspace_.scrollY;
|
||||
var svgRootNew = block.getSvgRoot();
|
||||
if (!svgRootNew) {
|
||||
throw 'block is not rendered.';
|
||||
}
|
||||
var xyNew = Blockly.getSvgXY_(svgRootNew, workspace);
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
xyNew.x += workspace.scrollX / workspace.scale - workspace.scrollX;
|
||||
xyNew.y += workspace.scrollY / workspace.scale - workspace.scrollY;
|
||||
if (workspace.toolbox_ && !workspace.scrollbar) {
|
||||
xyNew.x += workspace.toolbox_.width / workspace.scale;
|
||||
}
|
||||
block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);
|
||||
return block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter the blocks on the flyout to disable the ones that are above the
|
||||
* capacity limit.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue