UNPKG

monaco-editor

Version:
138 lines (137 loc) 6.27 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { addDisposableListener, h, EventType } from '../../../../../base/browser/dom.js'; import { renderIcon } from '../../../../../base/browser/ui/iconLabel/iconLabels.js'; import { Codicon } from '../../../../../base/common/codicons.js'; import { Disposable, toDisposable } from '../../../../../base/common/lifecycle.js'; import { autorunWithStore, derived } from '../../../../../base/common/observable.js'; import { LineRange, LineRangeSet } from '../../../../common/core/lineRange.js'; import { Range } from '../../../../common/core/range.js'; import { GlyphMarginLane } from '../../../../common/model.js'; import { localize } from '../../../../../nls.js'; export class RevertButtonsFeature extends Disposable { constructor(_editors, _diffModel, _options, _widget) { super(); this._editors = _editors; this._diffModel = _diffModel; this._options = _options; this._widget = _widget; const emptyArr = []; const selectedDiffs = derived(this, (reader) => { /** @description selectedDiffs */ const model = this._diffModel.read(reader); const diff = model === null || model === void 0 ? void 0 : model.diff.read(reader); if (!diff) { return emptyArr; } const selections = this._editors.modifiedSelections.read(reader); if (selections.every(s => s.isEmpty())) { return emptyArr; } const lineRanges = new LineRangeSet(selections.map(s => LineRange.fromRangeInclusive(s))); const mappings = diff.mappings.filter(m => m.lineRangeMapping.innerChanges && lineRanges.intersects(m.lineRangeMapping.modified)); const result = mappings.map(mapping => ({ mapping, rangeMappings: mapping.lineRangeMapping.innerChanges.filter(c => selections.some(s => Range.areIntersecting(c.modifiedRange, s))) })); if (result.length === 0 || result.every(r => r.rangeMappings.length === 0)) { return emptyArr; } return result; }); this._register(autorunWithStore((reader, store) => { const model = this._diffModel.read(reader); const diff = model === null || model === void 0 ? void 0 : model.diff.read(reader); if (!model || !diff) { return; } const movedTextToCompare = this._diffModel.read(reader).movedTextToCompare.read(reader); if (movedTextToCompare) { return; } if (!this._options.shouldRenderRevertArrows.read(reader)) { return; } const glyphWidgetsModified = []; const selectedDiffs_ = selectedDiffs.read(reader); const diffsSet = new Set(selectedDiffs_.map(d => d.mapping)); if (selectedDiffs_.length > 0) { const selections = this._editors.modifiedSelections.read(reader); const btn = store.add(new RevertButton(selections[selections.length - 1].positionLineNumber, this._widget, selectedDiffs_.flatMap(d => d.rangeMappings), true)); this._editors.modified.addGlyphMarginWidget(btn); glyphWidgetsModified.push(btn); } for (const m of diff.mappings) { if (diffsSet.has(m)) { continue; } if (!m.lineRangeMapping.modified.isEmpty && m.lineRangeMapping.innerChanges) { const btn = store.add(new RevertButton(m.lineRangeMapping.modified.startLineNumber, this._widget, m.lineRangeMapping.innerChanges, false)); this._editors.modified.addGlyphMarginWidget(btn); glyphWidgetsModified.push(btn); } } store.add(toDisposable(() => { for (const w of glyphWidgetsModified) { this._editors.modified.removeGlyphMarginWidget(w); } })); })); } } export class RevertButton extends Disposable { getId() { return this._id; } constructor(_lineNumber, _widget, _diffs, _selection) { super(); this._lineNumber = _lineNumber; this._widget = _widget; this._diffs = _diffs; this._selection = _selection; this._id = `revertButton${RevertButton.counter++}`; this._domNode = h('div.revertButton', { title: this._selection ? localize('revertSelectedChanges', 'Revert Selected Changes') : localize('revertChange', 'Revert Change') }, [renderIcon(Codicon.arrowRight)]).root; this._register(addDisposableListener(this._domNode, EventType.MOUSE_DOWN, e => { // don't prevent context menu from showing up if (e.button !== 2) { e.stopPropagation(); e.preventDefault(); } })); this._register(addDisposableListener(this._domNode, EventType.MOUSE_UP, e => { e.stopPropagation(); e.preventDefault(); })); this._register(addDisposableListener(this._domNode, EventType.CLICK, (e) => { this._widget.revertRangeMappings(this._diffs); e.stopPropagation(); e.preventDefault(); })); } /** * Get the dom node of the glyph widget. */ getDomNode() { return this._domNode; } /** * Get the placement of the glyph widget. */ getPosition() { return { lane: GlyphMarginLane.Right, range: { startColumn: 1, startLineNumber: this._lineNumber, endColumn: 1, endLineNumber: this._lineNumber, }, zIndex: 10001, }; } } RevertButton.counter = 0;