/** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @fileoverview Definition of the Blockly.tree.TreeNode class. * This class is similar to Closure's goog.ui.tree.TreeNode class. * @author samelh@google.com (Sam El-Husseini) */ 'use strict'; goog.provide('Blockly.tree.TreeNode'); goog.require('Blockly.tree.BaseNode'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.KeyCodes'); /** * A single node in the tree, customized for Blockly's UI. * Similar to Closure's goog.ui.tree.TreeNode * * @param {Blockly.Toolbox} toolbox The parent toolbox for this tree. * @param {string} content The content of the node label treated as * plain-text and will be HTML escaped. * @param {!Blockly.tree.BaseNode.Config} config The configuration for the tree. * @constructor * @extends {Blockly.tree.BaseNode} */ Blockly.tree.TreeNode = function(toolbox, content, config) { this.toolbox_ = toolbox; Blockly.tree.BaseNode.call(this, content, config); }; Blockly.utils.object.inherits(Blockly.tree.TreeNode, Blockly.tree.BaseNode); /** * Returns the tree. * @return {?Blockly.tree.TreeControl} The tree. * @override */ Blockly.tree.TreeNode.prototype.getTree = function() { if (this.tree) { return this.tree; } var parent = this.getParent(); if (parent) { var tree = parent.getTree(); if (tree) { this.setTreeInternal(tree); return tree; } } return null; }; /** * Returns the source for the icon. * @return {string} Src for the icon. * @override */ Blockly.tree.TreeNode.prototype.getCalculatedIconClass = function() { var expanded = this.getExpanded(); var expandedIconClass = this.getExpandedIconClass(); if (expanded && expandedIconClass) { return expandedIconClass; } var iconClass = this.getIconClass(); if (!expanded && iconClass) { return iconClass; } // fall back on default icons var config = this.getConfig(); if (this.hasChildren()) { if (expanded && config.cssExpandedFolderIcon) { return config.cssTreeIcon + ' ' + config.cssExpandedFolderIcon; } else if (!expanded && config.cssCollapsedFolderIcon) { return config.cssTreeIcon + ' ' + config.cssCollapsedFolderIcon; } } else { if (config.cssFileIcon) { return config.cssTreeIcon + ' ' + config.cssFileIcon; } } return ''; }; /** * Expand or collapse the node on mouse click. * @param {!Event} _e The browser event. * @override */ Blockly.tree.TreeNode.prototype.onClick_ = function(_e) { // Expand icon. if (this.hasChildren() && this.isUserCollapsible()) { this.toggle(); this.select(); } else if (this.isSelected()) { this.getTree().setSelectedItem(null); } else { this.select(); } this.updateRow(); }; /** * Suppress the inherited mouse down behaviour. * @param {!Event} _e The browser event. * @override * @private */ Blockly.tree.TreeNode.prototype.onMouseDown = function(_e) { // NOP }; /** * Remap event.keyCode in horizontalLayout so that arrow * keys work properly and call original onKeyDown handler. * @param {!Event} e The browser event. * @return {boolean} The handled value. * @override * @private */ Blockly.tree.TreeNode.prototype.onKeyDown = function(e) { if (this.tree.toolbox_.horizontalLayout_) { var map = {}; var next = Blockly.utils.KeyCodes.DOWN; var prev = Blockly.utils.KeyCodes.UP; map[Blockly.utils.KeyCodes.RIGHT] = this.isRightToLeft() ? prev : next; map[Blockly.utils.KeyCodes.LEFT] = this.isRightToLeft() ? next : prev; map[Blockly.utils.KeyCodes.UP] = Blockly.utils.KeyCodes.LEFT; map[Blockly.utils.KeyCodes.DOWN] = Blockly.utils.KeyCodes.RIGHT; var newKeyCode = map[e.keyCode]; Object.defineProperties(e, { keyCode: {value: newKeyCode || e.keyCode} }); } return Blockly.tree.TreeNode.superClass_.onKeyDown.call(this, e); }; /** * Set the handler that's triggered when the size of node has changed. * @param {function():?} fn The handler * @package */ Blockly.tree.TreeNode.prototype.onSizeChanged = function(fn) { this.onSizeChanged_ = fn; }; /** * Trigger a size changed event if a handler exists. * @private */ Blockly.tree.TreeNode.prototype.resizeToolbox_ = function() { if (this.onSizeChanged_) { this.onSizeChanged_.call(this.toolbox_); } }; /** * Resize the toolbox when a node is expanded. * @override */ Blockly.tree.TreeNode.prototype.doNodeExpanded = Blockly.tree.TreeNode.prototype.resizeToolbox_; /** * Resize the toolbox when a node is collased. * @override */ Blockly.tree.TreeNode.prototype.doNodeCollapsed = Blockly.tree.TreeNode.prototype.resizeToolbox_;