UNPKG

alm

Version:

The best IDE for TypeScript

236 lines (235 loc) 10.4 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); /** * Provides a new overview of the cotents of the file, *semantically* */ /** imports */ var ui = require("../../ui"); var csx = require("../../base/csx"); var React = require("react"); var ReactDOM = require("react-dom"); var state = require("../../state/state"); var react_redux_1 = require("react-redux"); var utils = require("../../../common/utils"); var socketClient_1 = require("../../../socket/socketClient"); var commands = require("../../commands/commands"); var typestyle = require("typestyle"); var styles = require("../../styles/styles"); var pure_1 = require("../../../common/pure"); var monacoUtils_1 = require("../../monaco/monacoUtils"); var SemanticViewStyles; (function (SemanticViewStyles) { SemanticViewStyles.root = { padding: '5px', background: '#343333', // Font color: '#BBB', fontSize: '.6rem', fontWeight: 'bold', // Overflow overflow: 'auto', // Limit width maxWidth: '200px', opacity: '0.7', transition: 'opacity .2s', ':hover': { opacity: '1' } }; SemanticViewStyles.nodeClass = typestyle.style(csx.extend(styles.ellipsis, { paddingTop: '2px', paddingBottom: '3px', paddingLeft: '2px', paddingRight: '2px', // Border which merges with the top marginTop: '-1px', border: '1px solid transparent', cursor: 'pointer', '-webkit-user-select': 'none', transition: 'background .2s', '&:hover': { backgroundColor: '#555' } })); SemanticViewStyles.selectedNodeClass = typestyle.style({ border: '1px solid grey', backgroundColor: styles.blackHighlightColor, $nest: { '&:hover': { backgroundColor: styles.blackHighlightColor } } }); })(SemanticViewStyles || (SemanticViewStyles = {})); var SemanticView = /** @class */ (function (_super) { __extends(SemanticView, _super); function SemanticView(props) { var _this = _super.call(this, props) || this; _this.handleCursorActivity = utils.debounce(function (editor) { if (editor === void 0) { editor = _this.props.editor; } if (!editor) return; // Still loading or maybe unloaded if (!state.inActiveProjectFilePath(_this.props.filePath)) return; if (_this.isUnmounted) return; if (!_this.props.showSemanticView) return; var sel = editor.getSelection(); var cursor = { line: sel.startLineNumber - 1, ch: sel.startColumn - 1 }; /** If first call OR cursor moved */ if (!_this.state.cursor || (_this.state.cursor && _this.state.cursor.line !== cursor.line)) { _this.setState({ cursor: cursor }); _this.afterComponentDidUpdate(function () { // Scroll to select node in view if any var ref = _this.refs[_this.selectedRef]; if (ref) { ref.scrollIntoViewIfNeeded(true); } }); } }, 1000); _this.gotoNode = function (node) { var cursor = { line: node.start.line, ch: node.start.ch }; var editor = _this.props.editor; monacoUtils_1.gotoPosition({ editor: editor, position: cursor }); editor.focus(); _this.setState({ cursor: cursor }); }; /** Constantly incrementing so that this points to the last (deepest) selected node :) */ _this.selectedRef = 0; _this.isSelected = function (node) { if (!_this.state.cursor) return ''; var cursor = _this.state.cursor; if (node.start.line <= cursor.line && node.end.line >= cursor.line) { _this.selectedRef++; return SemanticViewStyles.selectedNodeClass; } return ''; }; /** If the tree changes its width we need to relayout the editor */ _this.lastWidth = 0; /** Loads the tree data */ _this.reloadData = function () { if (!_this.props.filePath) return; if (!state.inActiveProjectFilePath(_this.props.filePath)) return; socketClient_1.server.getSemanticTree({ filePath: _this.props.filePath }).then(function (res) { _this.afterComponentDidUpdate(function () { // also relayout the editor if the last width is not the same as new width var newWidth = ReactDOM.findDOMNode(_this).clientWidth; if (_this.lastWidth !== newWidth) { _this.relayoutEditor(); _this.lastWidth = newWidth; } }); _this.setState({ tree: res.nodes }); }); }; _this.state = { tree: [] }; return _this; } SemanticView.prototype.shouldComponentUpdate = function () { return pure_1.shouldComponentUpdate.apply(this, arguments); }; SemanticView.prototype.componentWillUnmount = function () { _super.prototype.componentWillUnmount.call(this); }; SemanticView.prototype.componentWillReceiveProps = function (props) { var _this = this; if (props.showSemanticView && !this.props.showSemanticView) { this.handleCursorActivity(); } if (!this.props.editor && props.editor) { /** Initial data load */ var sel = props.editor.getSelection(); var cursor = { line: sel.startLineNumber - 1, ch: sel.endLineNumber - 1 }; this.setState({ cursor: cursor }); this.reloadData(); var reloadDataDebounced_1 = utils.debounce(this.reloadData, 3000); this.disposible.add(commands.fileContentsChanged.on(function (e) { if (e.filePath === props.filePath && _this.props.showSemanticView) { reloadDataDebounced_1(); } })); this.disposible.add(state.subscribeSub((function (s) { return s.showSemanticView; }), function (showSemanticView) { if (showSemanticView) { reloadDataDebounced_1(); } })); this.handleCursorActivity(props.editor); this.disposible.add(props.editor.onDidChangeCursorSelection(function () { return _this.handleCursorActivity(); })); } /** * If just hidden and we have an editor, then the editor needs resizing */ if (!props.showSemanticView && this.props.showSemanticView && this.props.editor) { this.afterComponentDidUpdate(function () { _this.relayoutEditor(); }); } }; SemanticView.prototype.render = function () { var _this = this; if (!this.props.showSemanticView || !this.state.cursor) { return React.createElement("div", null); } if (!state.inActiveProjectFilePath(this.props.filePath)) { return React.createElement("div", null); } return React.createElement("div", { style: SemanticViewStyles.root }, this.state.tree.map(function (node) { return _this.renderNode(node, 0); })); }; SemanticView.prototype.renderNode = function (node, indent) { var _this = this; var isSelected = this.isSelected(node); var color = ui.kindToColor(node.kind); var ref = isSelected ? this.selectedRef.toString() : null; return [React.createElement("div", { ref: ref, key: node.text, className: SemanticViewStyles.nodeClass + ' ' + isSelected, style: { color: color }, onClick: function (event) { _this.gotoNode(node); event.stopPropagation(); }, "data-start": node.start.line, "data-end": node.end.line }, ui.indent(indent), React.createElement("span", { style: { fontFamily: 'FontAwesome' } }, this.getIconForKind(node.kind)), " ", node.text)].concat(node.subNodes.map(function (sn) { return _this.renderNode(sn, indent + 1); })); }; SemanticView.prototype.getIconForKind = function (kind) { return ui.kindToIcon(kind); }; SemanticView.prototype.relayoutEditor = function () { // We store `top` (and restore it) otherwise the editor jumps around a bit after relayout. var top = this.props.editor.getScrollTop(); this.props.editor.layout(); this.props.editor.setScrollTop(top); }; SemanticView = __decorate([ react_redux_1.connect(function (state) { return { showSemanticView: state.showSemanticView, }; }), __metadata("design:paramtypes", [Object]) ], SemanticView); return SemanticView; }(ui.BaseComponent)); exports.SemanticView = SemanticView;