Files
blockly/core/components/tree/treenode.js
Sam El-Husseini dbcdaf0d21 Foundation for no-closure toolbox (#2818)
* A subset of closure tree components for building a no-closure toolbox
2019-08-14 11:22:21 -07:00

189 lines
5.1 KiB
JavaScript

/**
* @license
* Visual Blocks Editor
*
* Copyright 2019 Google Inc.
* https://developers.google.com/blockly/
*
* 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.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);
};
goog.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_;