mirror of
https://github.com/Microsoft/vscode
synced 2024-10-02 09:18:59 +00:00
Merge pull request #185592 from microsoft/hediet/b/horizontal-ladybug
Diff Editor v2 Improvements
This commit is contained in:
commit
085399feff
|
@ -100,6 +100,7 @@
|
|||
"--vscode-diffEditor-removedLineBackground",
|
||||
"--vscode-diffEditor-removedTextBackground",
|
||||
"--vscode-diffEditor-removedTextBorder",
|
||||
"--vscode-diffEditor-unchangedCodeBackground",
|
||||
"--vscode-diffEditor-unchangedRegionBackground",
|
||||
"--vscode-diffEditor-unchangedRegionForeground",
|
||||
"--vscode-diffEditorGutter-insertedLineBackground",
|
||||
|
|
|
@ -235,10 +235,10 @@ function handleGetFileChangesRequest(watcher: DirWatcher, fileServer: FileServer
|
|||
function makeLoaderJsHotReloadable(loaderJsCode: string, fileChangesUrl: URL): string {
|
||||
loaderJsCode = loaderJsCode.replace(
|
||||
/constructor\(env, scriptLoader, defineFunc, requireFunc, loaderAvailableTimestamp = 0\) {/,
|
||||
'$&globalThis.$$globalModuleManager = this;'
|
||||
'$&globalThis.___globalModuleManager = this;'
|
||||
);
|
||||
|
||||
const $$globalModuleManager: any = undefined;
|
||||
const ___globalModuleManager: any = undefined;
|
||||
|
||||
// This code will be appended to loader.js
|
||||
function $watchChanges(fileChangesUrl: string) {
|
||||
|
@ -266,24 +266,26 @@ function makeLoaderJsHotReloadable(loaderJsCode: string, fileChangesUrl: URL): s
|
|||
const data = JSON.parse(line);
|
||||
let handled = false;
|
||||
if (data.changedPath.endsWith('.css')) {
|
||||
console.log('css changed', data.changedPath);
|
||||
const styleSheet = [...document.querySelectorAll(`link[rel='stylesheet']`)].find((l: any) => new URL(l.href, document.location.href).pathname.endsWith(data.changedPath)) as any;
|
||||
if (styleSheet) {
|
||||
styleSheet.href = styleSheet.href.replace(/\?.*/, '') + '?' + Date.now();
|
||||
if (typeof document !== 'undefined') {
|
||||
console.log('css changed', data.changedPath);
|
||||
const styleSheet = [...document.querySelectorAll(`link[rel='stylesheet']`)].find((l: any) => new URL(l.href, document.location.href).pathname.endsWith(data.changedPath)) as any;
|
||||
if (styleSheet) {
|
||||
styleSheet.href = styleSheet.href.replace(/\?.*/, '') + '?' + Date.now();
|
||||
}
|
||||
}
|
||||
handled = true;
|
||||
} else if (data.changedPath.endsWith('.js') && data.moduleId) {
|
||||
console.log('js changed', data.changedPath);
|
||||
const moduleId = $$globalModuleManager._moduleIdProvider.getModuleId(data.moduleId);
|
||||
if ($$globalModuleManager._modules2[moduleId]) {
|
||||
const srcUrl = $$globalModuleManager._config.moduleIdToPaths(data.moduleId);
|
||||
const moduleId = ___globalModuleManager._moduleIdProvider.getModuleId(data.moduleId);
|
||||
if (___globalModuleManager._modules2[moduleId]) {
|
||||
const srcUrl = ___globalModuleManager._config.moduleIdToPaths(data.moduleId);
|
||||
const newSrc = await (await fetch(srcUrl)).text();
|
||||
(new Function('define', newSrc))(function (deps, callback) {
|
||||
const oldModule = $$globalModuleManager._modules2[moduleId];
|
||||
delete $$globalModuleManager._modules2[moduleId];
|
||||
const oldModule = ___globalModuleManager._modules2[moduleId];
|
||||
delete ___globalModuleManager._modules2[moduleId];
|
||||
|
||||
$$globalModuleManager.defineModule(data.moduleId, deps, callback);
|
||||
const newModule = $$globalModuleManager._modules2[moduleId];
|
||||
___globalModuleManager.defineModule(data.moduleId, deps, callback);
|
||||
const newModule = ___globalModuleManager._modules2[moduleId];
|
||||
const oldExports = { ...oldModule.exports };
|
||||
|
||||
Object.assign(oldModule.exports, newModule.exports);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { h } from 'vs/base/browser/dom';
|
||||
import { $, h } from 'vs/base/browser/dom';
|
||||
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
|
||||
import { findLast } from 'vs/base/common/arrays';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
|
@ -25,7 +25,7 @@ import { ViewZoneManager } from 'vs/editor/browser/widget/diffEditorWidget2/line
|
|||
import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines';
|
||||
import { OverviewRulerPart } from 'vs/editor/browser/widget/diffEditorWidget2/overviewRulerPart';
|
||||
import { UnchangedRangesFeature } from 'vs/editor/browser/widget/diffEditorWidget2/unchangedRanges';
|
||||
import { ObservableElementSizeObserver, applyObservableDecorations, deepMerge, readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
|
||||
import { ObservableElementSizeObserver, applyObservableDecorations, applyStyle, deepMerge, readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
|
||||
import { WorkerBasedDocumentDiffProvider } from 'vs/editor/browser/widget/workerBasedDocumentDiffProvider';
|
||||
import { EditorOptions, IDiffEditorOptions, IEditorOptions, ValidDiffEditorBaseOptions, clampedFloat, clampedInt, boolean as validateBooleanOption, stringSet as validateStringSetOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { IDimension } from 'vs/editor/common/core/dimension';
|
||||
|
@ -68,6 +68,7 @@ const diffEditorDefaultOptions: ValidDiffEditorBaseOptions = {
|
|||
|
||||
export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
|
||||
private readonly elements = h('div.monaco-diff-editor.side-by-side', { style: { position: 'relative', height: '100%' } }, [
|
||||
h('div.noModificationsOverlay@overlay', { style: { position: 'absolute', height: '100%', visibility: 'hidden', } }, [$('span', {}, 'No Changes')]),
|
||||
h('div.editor.original@original', { style: { position: 'absolute', height: '100%' } }),
|
||||
h('div.editor.modified@modified', { style: { position: 'absolute', height: '100%' } }),
|
||||
]);
|
||||
|
@ -190,6 +191,11 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
|
|||
this._originalEditor,
|
||||
this._modifiedEditor,
|
||||
));
|
||||
|
||||
this._register(applyStyle(this.elements.overlay, {
|
||||
width: this._layoutInfo.map((i, r) => i.originalEditor.width + (this._options.read(r).renderSideBySide ? 0 : i.modifiedEditor.width)),
|
||||
visibility: this._diffModel.map((m, r) => (m && m.hideUnchangedRegions.read(r) && m.diff.read(r)?.mappings.length === 0) ? 'visible' : 'hidden'),
|
||||
}));
|
||||
}
|
||||
|
||||
private readonly _layoutInfo = derived('modifiedEditorLayoutInfo', (reader) => {
|
||||
|
|
|
@ -31,8 +31,19 @@ export class DiffModel extends Disposable implements IDiffEditorViewModel {
|
|||
'unchangedRegion',
|
||||
{ regions: [], originalDecorationIds: [], modifiedDecorationIds: [] }
|
||||
);
|
||||
public readonly unchangedRegions: IObservable<UnchangedRegion[]> = derived('unchangedRegions', r =>
|
||||
this._hideUnchangedRegions.read(r) ? this._unchangedRegions.read(r).regions : []
|
||||
public readonly unchangedRegions: IObservable<UnchangedRegion[]> = derived('unchangedRegions', r => {
|
||||
if (this.hideUnchangedRegions.read(r)) {
|
||||
return this._unchangedRegions.read(r).regions;
|
||||
} else {
|
||||
// Reset state
|
||||
transaction(tx => {
|
||||
for (const r of this._unchangedRegions.get().regions) {
|
||||
r.setState(0, 0, tx);
|
||||
}
|
||||
});
|
||||
return [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public readonly syncedMovedTexts = observableValue<MovedText | undefined>('syncedMovedText', undefined);
|
||||
|
@ -41,7 +52,7 @@ export class DiffModel extends Disposable implements IDiffEditorViewModel {
|
|||
public readonly model: IDiffEditorModel,
|
||||
ignoreTrimWhitespace: IObservable<boolean>,
|
||||
maxComputationTimeMs: IObservable<number>,
|
||||
private readonly _hideUnchangedRegions: IObservable<boolean>,
|
||||
public readonly hideUnchangedRegions: IObservable<boolean>,
|
||||
private readonly _showMoves: IObservable<boolean>,
|
||||
documentDiffProvider: IDocumentDiffProvider,
|
||||
) {
|
||||
|
@ -74,7 +85,7 @@ export class DiffModel extends Disposable implements IDiffEditorViewModel {
|
|||
}
|
||||
|
||||
const textEdits = TextEditInfo.fromModelContentChanges(e.changes);
|
||||
const result = applyModifiedEdits(this._lastDiff!, textEdits, model.original, model.modified);
|
||||
const result = applyOriginalEdits(this._lastDiff!, textEdits, model.original, model.modified);
|
||||
if (result) {
|
||||
this._lastDiff = result;
|
||||
this._diff.set(DiffState.fromDiffResult(this._lastDiff), undefined);
|
||||
|
@ -171,6 +182,9 @@ export class DiffModel extends Disposable implements IDiffEditorViewModel {
|
|||
}
|
||||
|
||||
public ensureModifiedLineIsVisible(lineNumber: number, tx: ITransaction): void {
|
||||
if (this.diff.get()?.mappings.length === 0) {
|
||||
return;
|
||||
}
|
||||
const unchangedRegions = this._unchangedRegions.get().regions;
|
||||
for (const r of unchangedRegions) {
|
||||
if (r.getHiddenModifiedRange(undefined).contains(lineNumber)) {
|
||||
|
@ -181,6 +195,9 @@ export class DiffModel extends Disposable implements IDiffEditorViewModel {
|
|||
}
|
||||
|
||||
public ensureOriginalLineIsVisible(lineNumber: number, tx: ITransaction): void {
|
||||
if (this.diff.get()?.mappings.length === 0) {
|
||||
return;
|
||||
}
|
||||
const unchangedRegions = this._unchangedRegions.get().regions;
|
||||
for (const r of unchangedRegions) {
|
||||
if (r.getHiddenOriginalRange(undefined).contains(lineNumber)) {
|
||||
|
@ -251,8 +268,10 @@ export class UnchangedRegion {
|
|||
let modStart = mapping.modifiedRange.startLineNumber;
|
||||
let length = mapping.originalRange.length;
|
||||
|
||||
if (origStart === 1 && length > minContext + minHiddenLineCount) {
|
||||
length -= minContext;
|
||||
if (origStart === 1 && modStart === 1 && length > minContext + minHiddenLineCount) {
|
||||
if (length < originalLineCount) {
|
||||
length -= minContext;
|
||||
}
|
||||
result.push(new UnchangedRegion(origStart, modStart, length, 0, 0));
|
||||
} else if (origStart + length === originalLineCount + 1 && length > minContext + minHiddenLineCount) {
|
||||
origStart += minContext;
|
||||
|
|
|
@ -335,8 +335,21 @@ export class ViewZoneManager extends Disposable {
|
|||
scrollState.restore(this._modifiedEditor);
|
||||
}));
|
||||
|
||||
this._register(this._originalEditor.onDidScrollChange(e => { this._modifiedEditor.setScrollLeft(e.scrollLeft); }));
|
||||
this._register(this._modifiedEditor.onDidScrollChange(e => { this._originalEditor.setScrollLeft(e.scrollLeft); }));
|
||||
let ignoreChange = false;
|
||||
this._register(this._originalEditor.onDidScrollChange(e => {
|
||||
if (e.scrollLeftChanged && !ignoreChange) {
|
||||
ignoreChange = true;
|
||||
this._modifiedEditor.setScrollLeft(e.scrollLeft);
|
||||
ignoreChange = false;
|
||||
}
|
||||
}));
|
||||
this._register(this._modifiedEditor.onDidScrollChange(e => {
|
||||
if (e.scrollLeftChanged && !ignoreChange) {
|
||||
ignoreChange = true;
|
||||
this._originalEditor.setScrollLeft(e.scrollLeft);
|
||||
ignoreChange = false;
|
||||
}
|
||||
}));
|
||||
|
||||
this._originalScrollTop = observableFromEvent(this._originalEditor.onDidScrollChange, () => this._originalEditor.getScrollTop());
|
||||
this._modifiedScrollTop = observableFromEvent(this._modifiedEditor.onDidScrollChange, () => this._modifiedEditor.getScrollTop());
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
}
|
||||
|
||||
.diff-hidden-lines {
|
||||
transform: translate(0px, -8px);
|
||||
height: 0px; /* The children each have a fixed height, the transform confuses the browser */
|
||||
transform: translate(0px, -10px);
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
@ -35,6 +36,19 @@
|
|||
transform: translate(0px, -6px);
|
||||
}
|
||||
|
||||
.diff-unchanged-lines {
|
||||
background: var(--vscode-diffEditor-unchangedCodeBackground);
|
||||
}
|
||||
|
||||
.noModificationsOverlay {
|
||||
z-index: 1;
|
||||
background: var(--vscode-editor-background);
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.diff-hidden-lines .center {
|
||||
background: var(--vscode-diffEditor-unchangedRegionBackground);
|
||||
|
|
|
@ -13,8 +13,10 @@ import { isDefined } from 'vs/base/common/types';
|
|||
import { ICodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { DiffModel, UnchangedRegion } from 'vs/editor/browser/widget/diffEditorWidget2/diffModel';
|
||||
import { PlaceholderViewZone, ViewZoneOverlayWidget, applyStyle, applyViewZones } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
|
||||
import { PlaceholderViewZone, ViewZoneOverlayWidget, applyObservableDecorations, applyStyle, applyViewZones } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { CursorChangeReason } from 'vs/editor/common/cursorEvents';
|
||||
import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model';
|
||||
|
||||
export class UnchangedRangesFeature extends Disposable {
|
||||
private _isUpdatingViewZones = false;
|
||||
|
@ -29,45 +31,51 @@ export class UnchangedRangesFeature extends Disposable {
|
|||
super();
|
||||
|
||||
this._register(this._originalEditor.onDidChangeCursorPosition(e => {
|
||||
const m = this._diffModel.get();
|
||||
transaction(tx => {
|
||||
for (const s of this._originalEditor.getSelections() || []) {
|
||||
m?.ensureOriginalLineIsVisible(s.getStartPosition().lineNumber, tx);
|
||||
m?.ensureOriginalLineIsVisible(s.getEndPosition().lineNumber, tx);
|
||||
}
|
||||
});
|
||||
if (e.reason === CursorChangeReason.Explicit) {
|
||||
const m = this._diffModel.get();
|
||||
transaction(tx => {
|
||||
for (const s of this._originalEditor.getSelections() || []) {
|
||||
m?.ensureOriginalLineIsVisible(s.getStartPosition().lineNumber, tx);
|
||||
m?.ensureOriginalLineIsVisible(s.getEndPosition().lineNumber, tx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._modifiedEditor.onDidChangeCursorPosition(e => {
|
||||
const m = this._diffModel.get();
|
||||
transaction(tx => {
|
||||
for (const s of this._modifiedEditor.getSelections() || []) {
|
||||
m?.ensureModifiedLineIsVisible(s.getStartPosition().lineNumber, tx);
|
||||
m?.ensureModifiedLineIsVisible(s.getEndPosition().lineNumber, tx);
|
||||
}
|
||||
});
|
||||
if (e.reason === CursorChangeReason.Explicit) {
|
||||
const m = this._diffModel.get();
|
||||
transaction(tx => {
|
||||
for (const s of this._modifiedEditor.getSelections() || []) {
|
||||
m?.ensureModifiedLineIsVisible(s.getStartPosition().lineNumber, tx);
|
||||
m?.ensureModifiedLineIsVisible(s.getEndPosition().lineNumber, tx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
const unchangedRegions = this._diffModel.map((m, reader) => m?.diff.read(reader)?.mappings.length === 0 ? [] : m?.unchangedRegions.read(reader) ?? []);
|
||||
|
||||
const viewZones = derivedWithStore('view zones', (reader, store) => {
|
||||
const origViewZones: IViewZone[] = [];
|
||||
const modViewZones: IViewZone[] = [];
|
||||
const sideBySide = this._sideBySide.read(reader);
|
||||
|
||||
const unchangedRegions = this._diffModel.read(reader)?.unchangedRegions.read(reader) ?? [];
|
||||
for (const r of unchangedRegions) {
|
||||
const curUnchangedRegions = unchangedRegions.read(reader);
|
||||
for (const r of curUnchangedRegions) {
|
||||
if (r.shouldHideControls(reader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
const d = derived('hiddenOriginalRangeStart', reader => r.getHiddenOriginalRange(reader).startLineNumber - 1);
|
||||
const origVz = new PlaceholderViewZone(d, 30);
|
||||
const origVz = new PlaceholderViewZone(d, 24);
|
||||
origViewZones.push(origVz);
|
||||
store.add(new CollapsedCodeOverlayWidget(this._originalEditor, origVz, r, !sideBySide));
|
||||
}
|
||||
{
|
||||
const d = derived('hiddenModifiedRangeStart', reader => r.getHiddenModifiedRange(reader).startLineNumber - 1);
|
||||
const modViewZone = new PlaceholderViewZone(d, 30);
|
||||
const modViewZone = new PlaceholderViewZone(d, 24);
|
||||
modViewZones.push(modViewZone);
|
||||
store.add(new CollapsedCodeOverlayWidget(this._modifiedEditor, modViewZone, r, false));
|
||||
}
|
||||
|
@ -76,28 +84,50 @@ export class UnchangedRangesFeature extends Disposable {
|
|||
return { origViewZones, modViewZones, };
|
||||
});
|
||||
|
||||
|
||||
const unchangedLinesDecoration: IModelDecorationOptions = {
|
||||
description: 'unchanged lines',
|
||||
className: 'diff-unchanged-lines',
|
||||
isWholeLine: true,
|
||||
};
|
||||
|
||||
this._register(applyObservableDecorations(this._originalEditor, derived('decorations', (reader) => {
|
||||
const curUnchangedRegions = unchangedRegions.read(reader);
|
||||
return curUnchangedRegions.map<IModelDeltaDecoration>(r => ({
|
||||
range: r.originalRange.toInclusiveRange()!,
|
||||
options: unchangedLinesDecoration,
|
||||
}));
|
||||
})));
|
||||
|
||||
this._register(applyObservableDecorations(this._modifiedEditor, derived('decorations', (reader) => {
|
||||
const curUnchangedRegions = unchangedRegions.read(reader);
|
||||
return curUnchangedRegions.map<IModelDeltaDecoration>(r => ({
|
||||
range: r.modifiedRange.toInclusiveRange()!,
|
||||
options: unchangedLinesDecoration,
|
||||
}));
|
||||
})));
|
||||
|
||||
this._register(applyViewZones(this._originalEditor, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));
|
||||
this._register(applyViewZones(this._modifiedEditor, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));
|
||||
|
||||
this._register(autorunWithStore2('update folded unchanged regions', (reader, store) => {
|
||||
const unchangedRegions = this._diffModel.read(reader)?.unchangedRegions.read(reader) ?? [];
|
||||
|
||||
this._originalEditor.setHiddenAreas(unchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));
|
||||
this._modifiedEditor.setHiddenAreas(unchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));
|
||||
const curUnchangedRegions = unchangedRegions.read(reader);
|
||||
this._originalEditor.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));
|
||||
this._modifiedEditor.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {
|
||||
private readonly _nodes = h('div.diff-hidden-lines', [
|
||||
h('div.top@top', { title: 'Show more above' }),
|
||||
h('div.top@top', { title: 'Click or drag to show more above' }),
|
||||
h('div.center@content', { style: { display: 'flex' } }, [
|
||||
h('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },
|
||||
[$('a', { title: 'Show all', role: 'button', onclick: () => { this._unchangedRegion.showAll(undefined); } }, ...renderLabelWithIcons('$(unfold)'))]
|
||||
),
|
||||
h('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),
|
||||
]),
|
||||
h('div.bottom@bottom', { title: 'Show more below', role: 'button' }),
|
||||
h('div.bottom@bottom', { title: 'Click or drag to show more below', role: 'button' }),
|
||||
]);
|
||||
|
||||
constructor(
|
||||
|
@ -123,6 +153,9 @@ class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {
|
|||
const editor = this._editor;
|
||||
|
||||
this._register(addDisposableListener(this._nodes.top, 'mousedown', e => {
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
this._nodes.top.classList.toggle('dragging', true);
|
||||
this._nodes.root.classList.toggle('dragging', true);
|
||||
e.preventDefault();
|
||||
|
@ -154,7 +187,9 @@ class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {
|
|||
}));
|
||||
|
||||
this._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {
|
||||
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
this._nodes.bottom.classList.toggle('dragging', true);
|
||||
this._nodes.root.classList.toggle('dragging', true);
|
||||
e.preventDefault();
|
||||
|
@ -176,12 +211,17 @@ class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {
|
|||
});
|
||||
|
||||
const mouseUpListener = addDisposableListener(document.body, 'mouseup', e => {
|
||||
this._unchangedRegion.isDragged.set(false, undefined);
|
||||
|
||||
if (!didMove) {
|
||||
const top = editor.getTopForLineNumber(this._unchangedRegion.modifiedRange.endLineNumberExclusive);
|
||||
|
||||
this._unchangedRegion.showMoreBelow(20, undefined);
|
||||
const top2 = editor.getTopForLineNumber(this._unchangedRegion.modifiedRange.endLineNumberExclusive);
|
||||
editor.setScrollTop(editor.getScrollTop() + (top2 - top));
|
||||
}
|
||||
this._nodes.bottom.classList.toggle('dragging', false);
|
||||
this._nodes.root.classList.toggle('dragging', false);
|
||||
this._unchangedRegion.isDragged.set(false, undefined);
|
||||
mouseMoveListener.dispose();
|
||||
mouseUpListener.dispose();
|
||||
});
|
||||
|
|
|
@ -264,6 +264,8 @@ export interface CSSStyle {
|
|||
height: number | string;
|
||||
width: number | string;
|
||||
top: number | string;
|
||||
visibility: 'visible' | 'hidden' | 'collapse';
|
||||
display: 'block' | 'inline' | 'inline-block' | 'flex' | 'none';
|
||||
}
|
||||
|
||||
export function applyStyle(domNode: HTMLElement, style: Partial<{ [TKey in keyof CSSStyle]: CSSStyle[TKey] | IObservable<CSSStyle[TKey] | undefined> | undefined }>) {
|
||||
|
|
|
@ -210,7 +210,11 @@ export interface ICoordinatesConverter {
|
|||
validateViewRange(viewRange: Range, expectedModelRange: Range): Range;
|
||||
|
||||
// Model -> View conversion and related methods
|
||||
convertModelPositionToViewPosition(modelPosition: Position, affinity?: PositionAffinity, allowZeroLineNumber?: boolean): Position;
|
||||
/**
|
||||
* @param allowZeroLineNumber Should it return 0 when there are hidden lines at the top and the position is in the hidden area?
|
||||
* @param belowHiddenRanges When the model position is in a hidden area, should it return the first view position after or before?
|
||||
*/
|
||||
convertModelPositionToViewPosition(modelPosition: Position, affinity?: PositionAffinity, allowZeroLineNumber?: boolean, belowHiddenRanges?: boolean): Position;
|
||||
/**
|
||||
* @param affinity Only has an effect if the range is empty.
|
||||
*/
|
||||
|
|
|
@ -82,7 +82,7 @@ export class ViewModelDecorations implements IDisposable {
|
|||
const options = modelDecoration.options;
|
||||
let viewRange: Range;
|
||||
if (options.isWholeLine) {
|
||||
const start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1), PositionAffinity.Left);
|
||||
const start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1), PositionAffinity.Left, false, true);
|
||||
const end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)), PositionAffinity.Right);
|
||||
viewRange = new Range(start.lineNumber, start.column, end.lineNumber, end.column);
|
||||
} else {
|
||||
|
|
|
@ -830,16 +830,23 @@ export class ViewModelLinesFromProjectedModel implements IViewModelLines {
|
|||
return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
|
||||
}
|
||||
|
||||
public convertModelPositionToViewPosition(_modelLineNumber: number, _modelColumn: number, affinity: PositionAffinity = PositionAffinity.None, allowZeroLineNumber: boolean = false): Position {
|
||||
public convertModelPositionToViewPosition(_modelLineNumber: number, _modelColumn: number, affinity: PositionAffinity = PositionAffinity.None, allowZeroLineNumber: boolean = false, belowHiddenRanges: boolean = false): Position {
|
||||
|
||||
const validPosition = this.model.validatePosition(new Position(_modelLineNumber, _modelColumn));
|
||||
const inputLineNumber = validPosition.lineNumber;
|
||||
const inputColumn = validPosition.column;
|
||||
|
||||
let lineIndex = inputLineNumber - 1, lineIndexChanged = false;
|
||||
while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {
|
||||
lineIndex--;
|
||||
lineIndexChanged = true;
|
||||
if (belowHiddenRanges) {
|
||||
while (lineIndex < this.modelLineProjections.length && !this.modelLineProjections[lineIndex].isVisible()) {
|
||||
lineIndex++;
|
||||
lineIndexChanged = true;
|
||||
}
|
||||
} else {
|
||||
while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {
|
||||
lineIndex--;
|
||||
lineIndexChanged = true;
|
||||
}
|
||||
}
|
||||
if (lineIndex === 0 && !this.modelLineProjections[lineIndex].isVisible()) {
|
||||
// Could not reach a real line
|
||||
|
@ -851,7 +858,11 @@ export class ViewModelLinesFromProjectedModel implements IViewModelLines {
|
|||
|
||||
let r: Position;
|
||||
if (lineIndexChanged) {
|
||||
r = this.modelLineProjections[lineIndex].getViewPositionOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1), affinity);
|
||||
if (belowHiddenRanges) {
|
||||
r = this.modelLineProjections[lineIndex].getViewPositionOfModelPosition(deltaLineNumber, 1, affinity);
|
||||
} else {
|
||||
r = this.modelLineProjections[lineIndex].getViewPositionOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1), affinity);
|
||||
}
|
||||
} else {
|
||||
r = this.modelLineProjections[inputLineNumber - 1].getViewPositionOfModelPosition(deltaLineNumber, inputColumn, affinity);
|
||||
}
|
||||
|
@ -1071,8 +1082,8 @@ class CoordinatesConverter implements ICoordinatesConverter {
|
|||
|
||||
// Model -> View conversion and related methods
|
||||
|
||||
public convertModelPositionToViewPosition(modelPosition: Position, affinity?: PositionAffinity, allowZero?: boolean): Position {
|
||||
return this._lines.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column, affinity, allowZero);
|
||||
public convertModelPositionToViewPosition(modelPosition: Position, affinity?: PositionAffinity, allowZero?: boolean, belowHiddenRanges?: boolean): Position {
|
||||
return this._lines.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column, affinity, allowZero, belowHiddenRanges);
|
||||
}
|
||||
|
||||
public convertModelRangeToViewRange(modelRange: Range, affinity?: PositionAffinity): Range {
|
||||
|
|
|
@ -424,8 +424,9 @@ export const diffRemovedOutline = registerColor('diffEditor.removedTextBorder',
|
|||
export const diffBorder = registerColor('diffEditor.border', { dark: null, light: null, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('diffEditorBorder', 'Border color between the two text editors.'));
|
||||
export const diffDiagonalFill = registerColor('diffEditor.diagonalFill', { dark: '#cccccc33', light: '#22222233', hcDark: null, hcLight: null }, nls.localize('diffDiagonalFill', "Color of the diff editor's diagonal fill. The diagonal fill is used in side-by-side diff views."));
|
||||
|
||||
export const diffUnchangedRegionBackground = registerColor('diffEditor.unchangedRegionBackground', { dark: '#3e3e3e', light: '#e4e4e4', hcDark: null, hcLight: null }, nls.localize('diffEditor.unchangedRegionBackground', "The background color of unchanged blocks in diff editor."));
|
||||
export const diffUnchangedRegionForeground = registerColor('diffEditor.unchangedRegionForeground', { dark: '#a3a2a2', light: '#4d4c4c', hcDark: null, hcLight: null }, nls.localize('diffEditor.unchangedRegionForeground', "The foreground color of unchanged blocks in diff editor."));
|
||||
export const diffUnchangedRegionBackground = registerColor('diffEditor.unchangedRegionBackground', { dark: '#3e3e3e', light: '#e4e4e4', hcDark: null, hcLight: null }, nls.localize('diffEditor.unchangedRegionBackground', "The background color of unchanged blocks in the diff editor."));
|
||||
export const diffUnchangedRegionForeground = registerColor('diffEditor.unchangedRegionForeground', { dark: '#a3a2a2', light: '#4d4c4c', hcDark: null, hcLight: null }, nls.localize('diffEditor.unchangedRegionForeground', "The foreground color of unchanged blocks in the diff editor."));
|
||||
export const diffUnchangedTextBackground = registerColor('diffEditor.unchangedCodeBackground', { dark: '#74747429', light: '#b8b8b829', hcDark: null, hcLight: null }, nls.localize('diffEditor.unchangedCodeBackground', "The background color of unchanged code in the diff editor."));
|
||||
|
||||
/**
|
||||
* List and tree colors
|
||||
|
|
Loading…
Reference in a new issue