mirror of
https://github.com/google/blockly.git
synced 2026-01-07 00:50:27 +01:00
97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2021 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview The mixin that holds logic for setting a warning on a block if
|
|
* it is not inside a loop.
|
|
*/
|
|
'use strict';
|
|
|
|
goog.module('Blockly.loopMixin');
|
|
|
|
/* eslint-disable-next-line no-unused-vars */
|
|
const Abstract = goog.requireType('Blockly.Events.Abstract');
|
|
const Events = goog.require('Blockly.Events');
|
|
const Extensions = goog.require('Blockly.Extensions');
|
|
const Msg = goog.require('Blockly.Msg');
|
|
/* eslint-disable-next-line no-unused-vars */
|
|
const {Block} = goog.requireType('Blockly.Block');
|
|
|
|
|
|
/**
|
|
* This mixin adds a check to make sure the 'controls_flow_statements' block
|
|
* is contained in a loop. Otherwise a warning is added to the block.
|
|
* @mixin
|
|
* @augments Block
|
|
* @readonly
|
|
*/
|
|
const CONTROL_FLOW_IN_LOOP_CHECK_MIXIN = {
|
|
/**
|
|
* List of block types that are loops and thus do not need warnings.
|
|
* To add a new loop type add this to your code:
|
|
* Blockly.loopMixin.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.push('custom_loop');
|
|
*
|
|
* Please leave a comment on this github issue
|
|
* https://github.com/mit-cml/appinventor-sources/issues/2032 if you end up
|
|
* needing to use this.
|
|
*/
|
|
LOOP_TYPES: [
|
|
'controls_repeat',
|
|
'controls_repeat_ext',
|
|
'controls_forEach',
|
|
'controls_for',
|
|
'controls_whileUntil',
|
|
],
|
|
|
|
/**
|
|
* Is the given block enclosed (at any level) by a loop?
|
|
* @param {!Block} block Current block.
|
|
* @return {?Block} The nearest surrounding loop, or null if none.
|
|
*/
|
|
getSurroundLoop: function(block) {
|
|
let searchBlock = block;
|
|
// Is the block nested in a loop?
|
|
do {
|
|
if (CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.indexOf(
|
|
searchBlock.type) !== -1) {
|
|
return searchBlock;
|
|
}
|
|
searchBlock = searchBlock.getSurroundParent();
|
|
} while (searchBlock);
|
|
return null;
|
|
},
|
|
|
|
/**
|
|
* Called whenever anything on the workspace changes.
|
|
* Add warning if this flow block is not nested inside a loop.
|
|
* @param {!Abstract} e Change event.
|
|
* @this {Block}
|
|
*/
|
|
onchange: function(e) {
|
|
// Don't change state if:
|
|
// * It's at the start of a drag.
|
|
// * It's not a move event.
|
|
if (!this.workspace.isDragging || this.workspace.isDragging() ||
|
|
e.type !== Events.BLOCK_MOVE) {
|
|
return;
|
|
}
|
|
const enabled = !!CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(this);
|
|
this.setWarningText(
|
|
enabled ? null : Msg['CONTROLS_FLOW_STATEMENTS_WARNING']);
|
|
if (!this.isInFlyout) {
|
|
const group = Events.getGroup();
|
|
// Makes it so the move and the disable event get undone together.
|
|
Events.setGroup(e.group);
|
|
this.setEnabled(enabled);
|
|
Events.setGroup(group);
|
|
}
|
|
},
|
|
};
|
|
exports.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN = CONTROL_FLOW_IN_LOOP_CHECK_MIXIN;
|
|
|
|
Extensions.registerMixin(
|
|
'controls_flow_in_loop_check', CONTROL_FLOW_IN_LOOP_CHECK_MIXIN);
|