123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import { findFirstInSorted } from '../../../base/common/arrays.js';
- import { Emitter } from '../../../base/common/event.js';
- import { Range } from '../../common/core/range.js';
- import { countEOL } from '../../common/model/tokensStore.js';
- export class HiddenRangeModel {
- constructor(model) {
- this._updateEventEmitter = new Emitter();
- this._hasLineChanges = false;
- this._foldingModel = model;
- this._foldingModelListener = model.onDidChange(_ => this.updateHiddenRanges());
- this._hiddenRanges = [];
- if (model.regions.length) {
- this.updateHiddenRanges();
- }
- }
- get onDidChange() { return this._updateEventEmitter.event; }
- get hiddenRanges() { return this._hiddenRanges; }
- notifyChangeModelContent(e) {
- if (this._hiddenRanges.length && !this._hasLineChanges) {
- this._hasLineChanges = e.changes.some(change => {
- return change.range.endLineNumber !== change.range.startLineNumber || countEOL(change.text)[0] !== 0;
- });
- }
- }
- updateHiddenRanges() {
- let updateHiddenAreas = false;
- let newHiddenAreas = [];
- let i = 0; // index into hidden
- let k = 0;
- let lastCollapsedStart = Number.MAX_VALUE;
- let lastCollapsedEnd = -1;
- let ranges = this._foldingModel.regions;
- for (; i < ranges.length; i++) {
- if (!ranges.isCollapsed(i)) {
- continue;
- }
- let startLineNumber = ranges.getStartLineNumber(i) + 1; // the first line is not hidden
- let endLineNumber = ranges.getEndLineNumber(i);
- if (lastCollapsedStart <= startLineNumber && endLineNumber <= lastCollapsedEnd) {
- // ignore ranges contained in collapsed regions
- continue;
- }
- if (!updateHiddenAreas && k < this._hiddenRanges.length && this._hiddenRanges[k].startLineNumber === startLineNumber && this._hiddenRanges[k].endLineNumber === endLineNumber) {
- // reuse the old ranges
- newHiddenAreas.push(this._hiddenRanges[k]);
- k++;
- }
- else {
- updateHiddenAreas = true;
- newHiddenAreas.push(new Range(startLineNumber, 1, endLineNumber, 1));
- }
- lastCollapsedStart = startLineNumber;
- lastCollapsedEnd = endLineNumber;
- }
- if (this._hasLineChanges || updateHiddenAreas || k < this._hiddenRanges.length) {
- this.applyHiddenRanges(newHiddenAreas);
- }
- }
- applyMemento(state) {
- if (!Array.isArray(state) || state.length === 0) {
- return false;
- }
- let hiddenRanges = [];
- for (let r of state) {
- if (!r.startLineNumber || !r.endLineNumber) {
- return false;
- }
- hiddenRanges.push(new Range(r.startLineNumber + 1, 1, r.endLineNumber, 1));
- }
- this.applyHiddenRanges(hiddenRanges);
- return true;
- }
- /**
- * Collapse state memento, for persistence only, only used if folding model is not yet initialized
- */
- getMemento() {
- return this._hiddenRanges.map(r => ({ startLineNumber: r.startLineNumber - 1, endLineNumber: r.endLineNumber }));
- }
- applyHiddenRanges(newHiddenAreas) {
- this._hiddenRanges = newHiddenAreas;
- this._hasLineChanges = false;
- this._updateEventEmitter.fire(newHiddenAreas);
- }
- hasRanges() {
- return this._hiddenRanges.length > 0;
- }
- isHidden(line) {
- return findRange(this._hiddenRanges, line) !== null;
- }
- adjustSelections(selections) {
- let hasChanges = false;
- let editorModel = this._foldingModel.textModel;
- let lastRange = null;
- let adjustLine = (line) => {
- if (!lastRange || !isInside(line, lastRange)) {
- lastRange = findRange(this._hiddenRanges, line);
- }
- if (lastRange) {
- return lastRange.startLineNumber - 1;
- }
- return null;
- };
- for (let i = 0, len = selections.length; i < len; i++) {
- let selection = selections[i];
- let adjustedStartLine = adjustLine(selection.startLineNumber);
- if (adjustedStartLine) {
- selection = selection.setStartPosition(adjustedStartLine, editorModel.getLineMaxColumn(adjustedStartLine));
- hasChanges = true;
- }
- let adjustedEndLine = adjustLine(selection.endLineNumber);
- if (adjustedEndLine) {
- selection = selection.setEndPosition(adjustedEndLine, editorModel.getLineMaxColumn(adjustedEndLine));
- hasChanges = true;
- }
- selections[i] = selection;
- }
- return hasChanges;
- }
- dispose() {
- if (this.hiddenRanges.length > 0) {
- this._hiddenRanges = [];
- this._updateEventEmitter.fire(this._hiddenRanges);
- }
- if (this._foldingModelListener) {
- this._foldingModelListener.dispose();
- this._foldingModelListener = null;
- }
- }
- }
- function isInside(line, range) {
- return line >= range.startLineNumber && line <= range.endLineNumber;
- }
- function findRange(ranges, line) {
- let i = findFirstInSorted(ranges, r => line < r.startLineNumber) - 1;
- if (i >= 0 && ranges[i].endLineNumber >= line) {
- return ranges[i];
- }
- return null;
- }
|