From 57803997504d9161d289bd85e2da4c508e17c2fc Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Mon, 1 Mar 2021 10:00:47 -0800 Subject: [PATCH] Use registry for creating the no-category flyout (#4659) * Use registry for creating the horizontal / vertical flyout --- core/registry.js | 47 ++++++++++++++++++++++++----------------- core/toolbox/toolbox.js | 11 ++++------ core/workspace.js | 2 +- core/workspace_svg.js | 24 +++++++++------------ 4 files changed, 43 insertions(+), 41 deletions(-) diff --git a/core/registry.js b/core/registry.js index a11b9b8a7..d245cb396 100644 --- a/core/registry.js +++ b/core/registry.js @@ -180,12 +180,9 @@ Blockly.registry.unregister = function(type, name) { type = String(type).toLowerCase(); name = name.toLowerCase(); var typeRegistry = Blockly.registry.typeMap_[type]; - if (!typeRegistry) { - console.warn('No type "' + type + '" found'); - return; - } - if (!typeRegistry[name]) { - console.warn('No name "' + name + '" with type "' + type + '" found'); + if (!typeRegistry || !typeRegistry[name]) { + console.warn('Unable to unregister [' + name + '][' + type + '] from the ' + + 'registry.'); return; } delete Blockly.registry.typeMap_[type][name]; @@ -197,20 +194,24 @@ Blockly.registry.unregister = function(type, name) { * @param {string|!Blockly.registry.Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) + * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we + * are unable to find the plugin. * @return {?function(new:T, ...?)|Object} The class or object with the given * name and type or null if none exists. * @template T */ -Blockly.registry.getItem_ = function(type, name) { +Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) { type = String(type).toLowerCase(); name = name.toLowerCase(); var typeRegistry = Blockly.registry.typeMap_[type]; - if (!typeRegistry) { - console.warn('No type "' + type + '" found'); - return null; - } - if (!typeRegistry[name]) { - console.warn('No name "' + name + '" with type "' + type + '" found'); + if (!typeRegistry || !typeRegistry[name]) { + var msg = 'Unable to find [' + name + '][' + type + '] in the registry.'; + if (opt_throwIfMissing) { + throw new Error(msg + ' You must require or register a ' + type + + ' plugin.'); + } else { + console.warn(msg); + } return null; } return typeRegistry[name]; @@ -241,13 +242,15 @@ Blockly.registry.hasItem = function(type, name) { * @param {string|!Blockly.registry.Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) + * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we + * are unable to find the plugin. * @return {?function(new:T, ...?)} The class with the given name and type or * null if none exists. * @template T */ -Blockly.registry.getClass = function(type, name) { +Blockly.registry.getClass = function(type, name, opt_throwIfMissing) { return /** @type {?function(new:T, ...?)} */ ( - Blockly.registry.getItem_(type, name)); + Blockly.registry.getItem_(type, name, opt_throwIfMissing)); }; /** @@ -255,11 +258,14 @@ Blockly.registry.getClass = function(type, name) { * @param {string|!Blockly.registry.Type} type The type of the plugin. * (e.g. Category) * @param {string} name The plugin's name. (Ex. logic_category) + * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we + * are unable to find the object. * @returns {T} The object with the given name and type or null if none exists. * @template T */ -Blockly.registry.getObject = function(type, name) { - return /** @type {T} */ (Blockly.registry.getItem_(type, name)); +Blockly.registry.getObject = function(type, name, opt_throwIfMissing) { + return /** @type {T} */ ( + Blockly.registry.getItem_(type, name, opt_throwIfMissing)); }; /** @@ -268,10 +274,13 @@ Blockly.registry.getObject = function(type, name) { * @param {!Blockly.registry.Type} type The type of the plugin. * @param {!Blockly.Options} options The option object to check for the given * plugin. + * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we + * are unable to find the plugin. * @return {?function(new:T, ...?)} The class for the plugin. * @template T */ -Blockly.registry.getClassFromOptions = function(type, options) { +Blockly.registry.getClassFromOptions = function(type, options, + opt_throwIfMissing) { var typeName = type.toString(); var plugin = options.plugins[typeName] || Blockly.registry.DEFAULT; @@ -279,5 +288,5 @@ Blockly.registry.getClassFromOptions = function(type, options) { if (typeof plugin == 'function') { return plugin; } - return Blockly.registry.getClass(type, plugin); + return Blockly.registry.getClass(type, plugin, opt_throwIfMissing); }; diff --git a/core/toolbox/toolbox.js b/core/toolbox/toolbox.js index 8bf98f2f9..272ebb8a0 100644 --- a/core/toolbox/toolbox.js +++ b/core/toolbox/toolbox.js @@ -351,15 +351,12 @@ Blockly.Toolbox.prototype.createFlyout_ = function() { var FlyoutClass = null; if (workspace.horizontalLayout) { FlyoutClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, workspace.options); + Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, workspace.options, + true); } else { FlyoutClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX, workspace.options); - } - - if (!FlyoutClass) { - throw new Error('Blockly.VerticalFlyout, Blockly.HorizontalFlyout or your own' + - ' custom flyout must be required.'); + Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX, workspace.options, + true); } return new FlyoutClass(workspaceOptions); }; diff --git a/core/workspace.js b/core/workspace.js index 7d3fa4e47..5a1fb6345 100644 --- a/core/workspace.js +++ b/core/workspace.js @@ -51,7 +51,7 @@ Blockly.Workspace = function(opt_options) { this.toolboxPosition = this.options.toolboxPosition; var connectionCheckerClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.CONNECTION_CHECKER, this.options); + Blockly.registry.Type.CONNECTION_CHECKER, this.options, true); /** * An object that encapsulates logic for safety, type, and dragging checks. * @type {!Blockly.IConnectionChecker} diff --git a/core/workspace_svg.js b/core/workspace_svg.js index c3b4bc78b..e86162a56 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -17,6 +17,7 @@ goog.require('Blockly.BlockSvg'); goog.require('Blockly.browserEvents'); goog.require('Blockly.ConnectionDB'); goog.require('Blockly.constants'); +goog.require('Blockly.ContextMenu'); goog.require('Blockly.ContextMenuRegistry'); goog.require('Blockly.Events'); goog.require('Blockly.Events.BlockCreate'); @@ -81,7 +82,7 @@ Blockly.WorkspaceSvg = function( Blockly.WorkspaceSvg.superClass_.constructor.call(this, options); var MetricsManagerClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.METRICS_MANAGER, options); + Blockly.registry.Type.METRICS_MANAGER, options, true); /** * Object in charge of calculating metrics for the workspace. * @type {!Blockly.IMetricsManager} @@ -819,11 +820,8 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { // Determine if there needs to be a category tree, or a simple list of // blocks. This cannot be changed later, since the UI is very different. if (this.options.hasCategories) { - if (!Blockly.Toolbox) { - throw Error('Missing require for Blockly.Toolbox'); - } var ToolboxClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.TOOLBOX, this.options); + Blockly.registry.Type.TOOLBOX, this.options, true); this.toolbox_ = new ToolboxClass(this); } if (this.grid_) { @@ -833,7 +831,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { var CursorClass = Blockly.registry.getClassFromOptions( Blockly.registry.Type.CURSOR, this.options); - this.markerManager_.setCursor(new CursorClass()); + CursorClass && this.markerManager_.setCursor(new CursorClass()); this.renderer_.createDom(this.svgGroup_, this.getTheme()); return this.svgGroup_; @@ -992,15 +990,13 @@ Blockly.WorkspaceSvg.prototype.addFlyout = function(tagName) { })); workspaceOptions.toolboxPosition = this.options.toolboxPosition; if (this.horizontalLayout) { - if (!Blockly.HorizontalFlyout) { - throw Error('Missing require for Blockly.HorizontalFlyout'); - } - this.flyout_ = new Blockly.HorizontalFlyout(workspaceOptions); + var HorizontalFlyout = Blockly.registry.getClassFromOptions( + Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, this.options, true); + this.flyout_ = new HorizontalFlyout(workspaceOptions); } else { - if (!Blockly.VerticalFlyout) { - throw Error('Missing require for Blockly.VerticalFlyout'); - } - this.flyout_ = new Blockly.VerticalFlyout(workspaceOptions); + var VerticalFlyout = Blockly.registry.getClassFromOptions( + Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX, this.options, true); + this.flyout_ = new VerticalFlyout(workspaceOptions); } this.flyout_.autoClose = false; this.flyout_.getWorkspace().setVisible(true);