UNPKG

monaco-editor

Version:
320 lines (319 loc) • 14.4 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Emitter } from '../../../base/common/event.js'; import { FoldingRegions } from './foldingRanges.js'; var FoldingModel = /** @class */ (function () { function FoldingModel(textModel, decorationProvider) { this._updateEventEmitter = new Emitter(); this._textModel = textModel; this._decorationProvider = decorationProvider; this._regions = new FoldingRegions(new Uint32Array(0), new Uint32Array(0)); this._editorDecorationIds = []; this._isInitialized = false; } Object.defineProperty(FoldingModel.prototype, "regions", { get: function () { return this._regions; }, enumerable: true, configurable: true }); Object.defineProperty(FoldingModel.prototype, "onDidChange", { get: function () { return this._updateEventEmitter.event; }, enumerable: true, configurable: true }); Object.defineProperty(FoldingModel.prototype, "textModel", { get: function () { return this._textModel; }, enumerable: true, configurable: true }); Object.defineProperty(FoldingModel.prototype, "isInitialized", { get: function () { return this._isInitialized; }, enumerable: true, configurable: true }); FoldingModel.prototype.toggleCollapseState = function (regions) { var _this = this; if (!regions.length) { return; } var processed = {}; this._decorationProvider.changeDecorations(function (accessor) { for (var _i = 0, regions_1 = regions; _i < regions_1.length; _i++) { var region = regions_1[_i]; var index = region.regionIndex; var editorDecorationId = _this._editorDecorationIds[index]; if (editorDecorationId && !processed[editorDecorationId]) { processed[editorDecorationId] = true; var newCollapseState = !_this._regions.isCollapsed(index); _this._regions.setCollapsed(index, newCollapseState); accessor.changeDecorationOptions(editorDecorationId, _this._decorationProvider.getDecorationOption(newCollapseState)); } } }); this._updateEventEmitter.fire({ model: this, collapseStateChanged: regions }); }; FoldingModel.prototype.update = function (newRegions, blockedLineNumers) { var _this = this; if (blockedLineNumers === void 0) { blockedLineNumers = []; } var newEditorDecorations = []; var isBlocked = function (startLineNumber, endLineNumber) { for (var _i = 0, blockedLineNumers_1 = blockedLineNumers; _i < blockedLineNumers_1.length; _i++) { var blockedLineNumber = blockedLineNumers_1[_i]; if (startLineNumber < blockedLineNumber && blockedLineNumber <= endLineNumber) { // first line is visible return true; } } return false; }; var initRange = function (index, isCollapsed) { var startLineNumber = newRegions.getStartLineNumber(index); if (isCollapsed && isBlocked(startLineNumber, newRegions.getEndLineNumber(index))) { isCollapsed = false; } newRegions.setCollapsed(index, isCollapsed); var maxColumn = _this._textModel.getLineMaxColumn(startLineNumber); var decorationRange = { startLineNumber: startLineNumber, startColumn: maxColumn, endLineNumber: startLineNumber, endColumn: maxColumn }; newEditorDecorations.push({ range: decorationRange, options: _this._decorationProvider.getDecorationOption(isCollapsed) }); }; var i = 0; var nextCollapsed = function () { while (i < _this._regions.length) { var isCollapsed = _this._regions.isCollapsed(i); i++; if (isCollapsed) { return i - 1; } } return -1; }; var k = 0; var collapsedIndex = nextCollapsed(); while (collapsedIndex !== -1 && k < newRegions.length) { // get the latest range var decRange = this._textModel.getDecorationRange(this._editorDecorationIds[collapsedIndex]); if (decRange) { var collapsedStartLineNumber = decRange.startLineNumber; if (this._textModel.getLineMaxColumn(collapsedStartLineNumber) === decRange.startColumn) { // test that the decoration is still at the end otherwise it got deleted while (k < newRegions.length) { var startLineNumber = newRegions.getStartLineNumber(k); if (collapsedStartLineNumber >= startLineNumber) { initRange(k, collapsedStartLineNumber === startLineNumber); k++; } else { break; } } } } collapsedIndex = nextCollapsed(); } while (k < newRegions.length) { initRange(k, false); k++; } this._editorDecorationIds = this._decorationProvider.deltaDecorations(this._editorDecorationIds, newEditorDecorations); this._regions = newRegions; this._isInitialized = true; this._updateEventEmitter.fire({ model: this }); }; /** * Collapse state memento, for persistence only */ FoldingModel.prototype.getMemento = function () { var collapsedRanges = []; for (var i = 0; i < this._regions.length; i++) { if (this._regions.isCollapsed(i)) { var range = this._textModel.getDecorationRange(this._editorDecorationIds[i]); if (range) { var startLineNumber = range.startLineNumber; var endLineNumber = range.endLineNumber + this._regions.getEndLineNumber(i) - this._regions.getStartLineNumber(i); collapsedRanges.push({ startLineNumber: startLineNumber, endLineNumber: endLineNumber }); } } } if (collapsedRanges.length > 0) { return collapsedRanges; } return void 0; }; /** * Apply persisted state, for persistence only */ FoldingModel.prototype.applyMemento = function (state) { if (!Array.isArray(state)) { return; } var toToogle = []; for (var _i = 0, state_1 = state; _i < state_1.length; _i++) { var range = state_1[_i]; var region = this.getRegionAtLine(range.startLineNumber); if (region && !region.isCollapsed) { toToogle.push(region); } } this.toggleCollapseState(toToogle); }; FoldingModel.prototype.dispose = function () { this._decorationProvider.deltaDecorations(this._editorDecorationIds, []); }; FoldingModel.prototype.getAllRegionsAtLine = function (lineNumber, filter) { var result = []; if (this._regions) { var index = this._regions.findRange(lineNumber); var level = 1; while (index >= 0) { var current = this._regions.toRegion(index); if (!filter || filter(current, level)) { result.push(current); } level++; index = current.parentIndex; } } return result; }; FoldingModel.prototype.getRegionAtLine = function (lineNumber) { if (this._regions) { var index = this._regions.findRange(lineNumber); if (index >= 0) { return this._regions.toRegion(index); } } return null; }; FoldingModel.prototype.getRegionsInside = function (region, filter) { var result = []; var index = region ? region.regionIndex + 1 : 0; var endLineNumber = region ? region.endLineNumber : Number.MAX_VALUE; if (filter && filter.length === 2) { var levelStack = []; for (var i = index, len = this._regions.length; i < len; i++) { var current = this._regions.toRegion(i); if (this._regions.getStartLineNumber(i) < endLineNumber) { while (levelStack.length > 0 && !current.containedBy(levelStack[levelStack.length - 1])) { levelStack.pop(); } levelStack.push(current); if (filter(current, levelStack.length)) { result.push(current); } } else { break; } } } else { for (var i = index, len = this._regions.length; i < len; i++) { var current = this._regions.toRegion(i); if (this._regions.getStartLineNumber(i) < endLineNumber) { if (!filter || filter(current)) { result.push(current); } } else { break; } } } return result; }; return FoldingModel; }()); export { FoldingModel }; /** * Collapse or expand the regions at the given locations including all children. * @param doCollapse Wheter to collase or expand * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels. * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model. */ export function setCollapseStateLevelsDown(foldingModel, doCollapse, levels, lineNumbers) { if (levels === void 0) { levels = Number.MAX_VALUE; } var toToggle = []; if (lineNumbers && lineNumbers.length > 0) { for (var _i = 0, lineNumbers_1 = lineNumbers; _i < lineNumbers_1.length; _i++) { var lineNumber = lineNumbers_1[_i]; var region = foldingModel.getRegionAtLine(lineNumber); if (region) { if (region.isCollapsed !== doCollapse) { toToggle.push(region); } if (levels > 1) { var regionsInside = foldingModel.getRegionsInside(region, function (r, level) { return r.isCollapsed !== doCollapse && level < levels; }); toToggle.push.apply(toToggle, regionsInside); } } } } else { var regionsInside = foldingModel.getRegionsInside(null, function (r, level) { return r.isCollapsed !== doCollapse && level < levels; }); toToggle.push.apply(toToggle, regionsInside); } foldingModel.toggleCollapseState(toToggle); } /** * Collapse or expand the regions at the given locations including all parents. * @param doCollapse Wheter to collase or expand * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels. * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model. */ export function setCollapseStateLevelsUp(foldingModel, doCollapse, levels, lineNumbers) { var toToggle = []; for (var _i = 0, lineNumbers_2 = lineNumbers; _i < lineNumbers_2.length; _i++) { var lineNumber = lineNumbers_2[_i]; var regions = foldingModel.getAllRegionsAtLine(lineNumber, function (region, level) { return region.isCollapsed !== doCollapse && level <= levels; }); toToggle.push.apply(toToggle, regions); } foldingModel.toggleCollapseState(toToggle); } /** * Folds or unfolds all regions that have a given level, except if they contain one of the blocked lines. * @param foldLevel level. Level == 1 is the top level * @param doCollapse Wheter to collase or expand * @param blockedLineNumbers */ export function setCollapseStateAtLevel(foldingModel, foldLevel, doCollapse, blockedLineNumbers) { var filter = function (region, level) { return level === foldLevel && region.isCollapsed !== doCollapse && !blockedLineNumbers.some(function (line) { return region.containsLine(line); }); }; var toToggle = foldingModel.getRegionsInside(null, filter); foldingModel.toggleCollapseState(toToggle); } /** * Folds all regions for which the lines start with a given regex * @param foldingModel the folding model */ export function setCollapseStateForMatchingLines(foldingModel, regExp, doCollapse) { var editorModel = foldingModel.textModel; var regions = foldingModel.regions; var toToggle = []; for (var i = regions.length - 1; i >= 0; i--) { if (doCollapse !== regions.isCollapsed(i)) { var startLineNumber = regions.getStartLineNumber(i); if (regExp.test(editorModel.getLineContent(startLineNumber))) { toToggle.push(regions.toRegion(i)); } } } foldingModel.toggleCollapseState(toToggle); } /** * Folds all regions of the given type * @param foldingModel the folding model */ export function setCollapseStateForType(foldingModel, type, doCollapse) { var regions = foldingModel.regions; var toToggle = []; for (var i = regions.length - 1; i >= 0; i--) { if (doCollapse !== regions.isCollapsed(i) && type === regions.getType(i)) { toToggle.push(regions.toRegion(i)); } } foldingModel.toggleCollapseState(toToggle); }