mirror of
https://github.com/google/blockly.git
synced 2026-01-11 19:07:08 +01:00
Add plugin options (#3922)
* Adds a plugin through options * Fix requires * Fix pr comments
This commit is contained in:
@@ -110,6 +110,8 @@ Blockly.Options = function(options) {
|
||||
|
||||
var renderer = options['renderer'] || 'geras';
|
||||
|
||||
var plugins = options['plugins'] || {};
|
||||
|
||||
/** @type {boolean} */
|
||||
this.RTL = rtl;
|
||||
/** @type {boolean} */
|
||||
@@ -174,6 +176,12 @@ Blockly.Options = function(options) {
|
||||
* @type {Blockly.Workspace}
|
||||
*/
|
||||
this.parentWorkspace = options['parentWorkspace'];
|
||||
|
||||
/**
|
||||
* Map of plugin type to name of registered plugin or plugin class.
|
||||
* @type {!Object.<string, (function(new:?, ...?)|string)>}
|
||||
*/
|
||||
this.plugins = plugins;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
|
||||
goog.provide('Blockly.registry');
|
||||
|
||||
goog.requireType('Blockly.blockRendering.Renderer');
|
||||
goog.requireType('Blockly.Field');
|
||||
goog.requireType('Blockly.IToolbox');
|
||||
|
||||
|
||||
/**
|
||||
* A map of maps. With the keys being the type and name of the class we are
|
||||
@@ -23,6 +27,12 @@ goog.provide('Blockly.registry');
|
||||
*/
|
||||
Blockly.registry.typeMap_ = {};
|
||||
|
||||
/**
|
||||
* The string used to register the default class for a type of plugin.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.registry.DEFAULT = 'default';
|
||||
|
||||
/**
|
||||
* A name with the type of the element stored in the generic.
|
||||
* @param {string} name The name of the registry type.
|
||||
@@ -49,6 +59,9 @@ Blockly.registry.Type.RENDERER = new Blockly.registry.Type('renderer');
|
||||
/** @type {!Blockly.registry.Type<Blockly.Field>} */
|
||||
Blockly.registry.Type.FIELD = new Blockly.registry.Type('field');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IToolbox>} */
|
||||
Blockly.registry.Type.TOOLBOX = new Blockly.registry.Type('toolbox');
|
||||
|
||||
/**
|
||||
* Registers a class based on a type and name.
|
||||
* @param {string|Blockly.registry.Type<T>} type The type of the plugin.
|
||||
@@ -152,3 +165,23 @@ Blockly.registry.getClass = function(type, name) {
|
||||
}
|
||||
return typeRegistry[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the class name or the class from Blockly options for the given type.
|
||||
* This is used for plugins that override a built in feature. (Ex: Toolbox)
|
||||
* @param {Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {!Blockly.Options} options The option object to check for the given
|
||||
* plugin.
|
||||
* @return {?function(new:T, ...?)} The class for the plugin.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.getClassFromOptions = function(type, options) {
|
||||
var typeName = type.toString();
|
||||
var plugin = options.plugins[typeName] || Blockly.registry.DEFAULT;
|
||||
|
||||
// If the user passed in a plugin class instead of a registered plugin name.
|
||||
if (typeof plugin == 'function') {
|
||||
return plugin;
|
||||
}
|
||||
return Blockly.registry.getClass(type, plugin);
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Events');
|
||||
goog.require('Blockly.Events.Ui');
|
||||
goog.require('Blockly.navigation');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.Touch');
|
||||
goog.require('Blockly.tree.TreeControl');
|
||||
goog.require('Blockly.tree.TreeNode');
|
||||
@@ -917,3 +918,6 @@ Blockly.Css.register([
|
||||
'}'
|
||||
/* eslint-enable indent */
|
||||
]);
|
||||
|
||||
Blockly.registry.register(Blockly.registry.Type.TOOLBOX,
|
||||
Blockly.registry.DEFAULT, Blockly.Toolbox);
|
||||
|
||||
@@ -24,6 +24,7 @@ goog.require('Blockly.MarkerManager');
|
||||
goog.require('Blockly.Msg');
|
||||
goog.require('Blockly.navigation');
|
||||
goog.require('Blockly.Options');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.ThemeManager');
|
||||
goog.require('Blockly.Themes.Classic');
|
||||
goog.require('Blockly.TouchGesture');
|
||||
@@ -341,7 +342,7 @@ Blockly.WorkspaceSvg.prototype.flyout_ = null;
|
||||
/**
|
||||
* Category-based toolbox providing blocks which may be dragged into this
|
||||
* workspace.
|
||||
* @type {Blockly.Toolbox}
|
||||
* @type {Blockly.IToolbox}
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.toolbox_ = null;
|
||||
@@ -749,7 +750,9 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
|
||||
if (!Blockly.Toolbox) {
|
||||
throw Error('Missing require for Blockly.Toolbox');
|
||||
}
|
||||
this.toolbox_ = new Blockly.Toolbox(this);
|
||||
var ToolboxClass = Blockly.registry.getClassFromOptions(
|
||||
Blockly.registry.Type.TOOLBOX, this.options);
|
||||
this.toolbox_ = new ToolboxClass(this);
|
||||
}
|
||||
if (this.grid_) {
|
||||
this.grid_.update(this.scale);
|
||||
@@ -948,7 +951,7 @@ Blockly.WorkspaceSvg.prototype.getFlyout = function(opt_own) {
|
||||
|
||||
/**
|
||||
* Getter for the toolbox associated with this workspace, if one exists.
|
||||
* @return {Blockly.Toolbox} The toolbox on this workspace.
|
||||
* @return {Blockly.IToolbox} The toolbox on this workspace.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.getToolbox = function() {
|
||||
@@ -2232,7 +2235,7 @@ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) {
|
||||
|
||||
/**
|
||||
* Get the dimensions of the given workspace component, in pixels.
|
||||
* @param {Blockly.Toolbox|Blockly.Flyout} elem The element to get the
|
||||
* @param {Blockly.IToolbox|Blockly.Flyout} elem The element to get the
|
||||
* dimensions of, or null. It should be a toolbox or flyout, and should
|
||||
* implement getWidth() and getHeight().
|
||||
* @return {!Blockly.utils.Size} An object containing width and height
|
||||
|
||||
@@ -48,4 +48,40 @@ suite('Registry', function() {
|
||||
}, 'Can not register a null value');
|
||||
});
|
||||
});
|
||||
suite('getClassFromOptions', function() {
|
||||
setup(function() {
|
||||
this.defaultClass = function() {};
|
||||
this.defaultClass.prototype.testMethod = function() {
|
||||
return 'default';
|
||||
};
|
||||
this.options = {
|
||||
'plugins': {
|
||||
'test' : 'test_name'
|
||||
}
|
||||
};
|
||||
Blockly.registry.typeMap_['test'] = {
|
||||
'test_name': TestClass,
|
||||
'default': this.defaultClass
|
||||
};
|
||||
});
|
||||
test('Simple - Plugin name given', function() {
|
||||
var testClass = Blockly.registry.getClassFromOptions('test', this.options);
|
||||
chai.assert.instanceOf(new testClass(), TestClass);
|
||||
});
|
||||
test('Simple - Plugin class given', function() {
|
||||
this.options.plugins['test'] = TestClass;
|
||||
var testClass = Blockly.registry.getClassFromOptions('test', this.options);
|
||||
chai.assert.instanceOf(new testClass(), TestClass);
|
||||
});
|
||||
test('No Plugin Name Given', function() {
|
||||
delete this.options['plugins']['test'];
|
||||
var testClass = Blockly.registry.getClassFromOptions('test', this.options);
|
||||
chai.assert.instanceOf(new testClass(), this.defaultClass);
|
||||
});
|
||||
test('Incorrect Plugin Name', function() {
|
||||
this.options['plugins']['test'] = 'random';
|
||||
var testClass = Blockly.registry.getClassFromOptions('test', this.options);
|
||||
chai.assert.isNull(testClass);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user