Skip to content

Commit

Permalink
refactor: convert registry files to es6 classes (google#5940)
Browse files Browse the repository at this point in the history
* refactor: convert shortcut registry to es6 class

* refactor: convert context menu registry to es6 class

* refactor: convert registry type to es6 class

* chore: format

* chore: respond to PR comments
  • Loading branch information
rachel-fenichel authored Feb 18, 2022
1 parent b52c65c commit f1148f1
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 388 deletions.
183 changes: 93 additions & 90 deletions core/contextmenu_registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,101 @@ const {WorkspaceSvg} = goog.requireType('Blockly.WorkspaceSvg');
* Class for the registry of context menu items. This is intended to be a
* singleton. You should not create a new instance, and only access this class
* from ContextMenuRegistry.registry.
* @constructor
* @private
* @alias Blockly.ContextMenuRegistry
*/
const ContextMenuRegistry = function() {
// Singleton instance should be registered once.
ContextMenuRegistry.registry = this;
class ContextMenuRegistry {
/**
* @alias Blockly.ContextMenuRegistry
*/
constructor() {
this.reset();
}

/**
* Registry of all registered RegistryItems, keyed by ID.
* @type {!Object<string, !ContextMenuRegistry.RegistryItem>}
* @private
* Clear and recreate the registry.
*/
this.registry_ = Object.create(null);
};
reset() {
/**
* Registry of all registered RegistryItems, keyed by ID.
* @type {!Object<string, !ContextMenuRegistry.RegistryItem>}
* @private
*/
this.registry_ = Object.create(null);
}

/**
* Registers a RegistryItem.
* @param {!ContextMenuRegistry.RegistryItem} item Context menu item to
* register.
* @throws {Error} if an item with the given ID already exists.
*/
register(item) {
if (this.registry_[item.id]) {
throw Error('Menu item with ID "' + item.id + '" is already registered.');
}
this.registry_[item.id] = item;
}

/**
* Unregisters a RegistryItem with the given ID.
* @param {string} id The ID of the RegistryItem to remove.
* @throws {Error} if an item with the given ID does not exist.
*/
unregister(id) {
if (!this.registry_[id]) {
throw new Error('Menu item with ID "' + id + '" not found.');
}
delete this.registry_[id];
}

/**
* @param {string} id The ID of the RegistryItem to get.
* @return {?ContextMenuRegistry.RegistryItem} RegistryItem or null if not
* found
*/
getItem(id) {
return this.registry_[id] || null;
}

/**
* Gets the valid context menu options for the given scope type (e.g. block or
* workspace) and scope. Blocks are only shown if the preconditionFn shows
* they should not be hidden.
* @param {!ContextMenuRegistry.ScopeType} scopeType Type of scope where menu
* should be shown (e.g. on a block or on a workspace)
* @param {!ContextMenuRegistry.Scope} scope Current scope of context menu
* (i.e., the exact workspace or block being clicked on)
* @return {!Array<!ContextMenuRegistry.ContextMenuOption>} the list of
* ContextMenuOptions
*/
getContextMenuOptions(scopeType, scope) {
const menuOptions = [];
const registry = this.registry_;
Object.keys(registry).forEach(function(id) {
const item = registry[id];
if (scopeType === item.scopeType) {
const precondition = item.preconditionFn(scope);
if (precondition !== 'hidden') {
const displayText = typeof item.displayText === 'function' ?
item.displayText(scope) :
item.displayText;
/** @type {!ContextMenuRegistry.ContextMenuOption} */
const menuOption = {
text: displayText,
enabled: (precondition === 'enabled'),
callback: item.callback,
scope: scope,
weight: item.weight,
};
menuOptions.push(menuOption);
}
}
});
menuOptions.sort(function(a, b) {
return a.weight - b.weight;
});
return menuOptions;
}
}

/**
* Where this menu item should be rendered. If the menu item should be rendered
Expand Down Expand Up @@ -90,85 +170,8 @@ ContextMenuRegistry.ContextMenuOption;
/**
* Singleton instance of this class. All interactions with this class should be
* done on this object.
* @type {?ContextMenuRegistry}
*/
ContextMenuRegistry.registry = null;

/**
* Registers a RegistryItem.
* @param {!ContextMenuRegistry.RegistryItem} item Context menu item to
* register.
* @throws {Error} if an item with the given ID already exists.
*/
ContextMenuRegistry.prototype.register = function(item) {
if (this.registry_[item.id]) {
throw Error('Menu item with ID "' + item.id + '" is already registered.');
}
this.registry_[item.id] = item;
};

/**
* Unregisters a RegistryItem with the given ID.
* @param {string} id The ID of the RegistryItem to remove.
* @throws {Error} if an item with the given ID does not exist.
*/
ContextMenuRegistry.prototype.unregister = function(id) {
if (!this.registry_[id]) {
throw new Error('Menu item with ID "' + id + '" not found.');
}
delete this.registry_[id];
};

/**
* @param {string} id The ID of the RegistryItem to get.
* @return {?ContextMenuRegistry.RegistryItem} RegistryItem or null if not found
* @type {!ContextMenuRegistry}
*/
ContextMenuRegistry.prototype.getItem = function(id) {
return this.registry_[id] || null;
};

/**
* Gets the valid context menu options for the given scope type (e.g. block or
* workspace) and scope. Blocks are only shown if the preconditionFn shows they
* should not be hidden.
* @param {!ContextMenuRegistry.ScopeType} scopeType Type of scope where menu
* should be shown (e.g. on a block or on a workspace)
* @param {!ContextMenuRegistry.Scope} scope Current scope of context menu
* (i.e., the exact workspace or block being clicked on)
* @return {!Array<!ContextMenuRegistry.ContextMenuOption>} the list of
* ContextMenuOptions
*/
ContextMenuRegistry.prototype.getContextMenuOptions = function(
scopeType, scope) {
const menuOptions = [];
const registry = this.registry_;
Object.keys(registry).forEach(function(id) {
const item = registry[id];
if (scopeType === item.scopeType) {
const precondition = item.preconditionFn(scope);
if (precondition !== 'hidden') {
const displayText = typeof item.displayText === 'function' ?
item.displayText(scope) :
item.displayText;
/** @type {!ContextMenuRegistry.ContextMenuOption} */
const menuOption = {
text: displayText,
enabled: (precondition === 'enabled'),
callback: item.callback,
scope: scope,
weight: item.weight,
};
menuOptions.push(menuOption);
}
}
});
menuOptions.sort(function(a, b) {
return a.weight - b.weight;
});
return menuOptions;
};

// Creates and assigns the singleton instance.
new ContextMenuRegistry();
ContextMenuRegistry.registry = new ContextMenuRegistry();

exports.ContextMenuRegistry = ContextMenuRegistry;
35 changes: 19 additions & 16 deletions core/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,31 @@ exports.DEFAULT = DEFAULT;

/**
* A name with the type of the element stored in the generic.
* @param {string} name The name of the registry type.
* @constructor
* @template T
* @alias Blockly.registry.Type
*/
const Type = function(name) {
class Type {
/**
* @type {string}
* @private
* @param {string} name The name of the registry type.
* @alias Blockly.registry.Type
*/
this.name_ = name;
};
constructor(name) {
/**
* @type {string}
* @private
*/
this.name_ = name;
}

/**
* Returns the name of the type.
* @return {string} The name.
*/
toString() {
return this.name_;
}
}
exports.Type = Type;

/**
* Returns the name of the type.
* @return {string} The name.
* @override
*/
Type.prototype.toString = function() {
return this.name_;
};

/** @type {!Type<IConnectionChecker>} */
Type.CONNECTION_CHECKER = new Type('connectionChecker');
Expand Down
Loading

0 comments on commit f1148f1

Please sign in to comment.