@theia/scm 1.64.0-next.28 → 1.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/decorations/scm-decorations-service.d.ts.map +1 -1
- package/lib/browser/decorations/scm-decorations-service.js +19 -1
- package/lib/browser/decorations/scm-decorations-service.js.map +1 -1
- package/lib/browser/merge-editor/merge-editor-contribution.d.ts +34 -0
- package/lib/browser/merge-editor/merge-editor-contribution.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor-contribution.js +335 -0
- package/lib/browser/merge-editor/merge-editor-contribution.js.map +1 -0
- package/lib/browser/merge-editor/merge-editor-dev-contribution.d.ts +31 -0
- package/lib/browser/merge-editor/merge-editor-dev-contribution.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor-dev-contribution.js +151 -0
- package/lib/browser/merge-editor/merge-editor-dev-contribution.js.map +1 -0
- package/lib/browser/merge-editor/merge-editor-module.d.ts +24 -0
- package/lib/browser/merge-editor/merge-editor-module.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor-module.js +109 -0
- package/lib/browser/merge-editor/merge-editor-module.js.map +1 -0
- package/lib/browser/merge-editor/merge-editor.d.ts +122 -0
- package/lib/browser/merge-editor/merge-editor.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor.js +560 -0
- package/lib/browser/merge-editor/merge-editor.js.map +1 -0
- package/lib/browser/merge-editor/model/line-range.d.ts +37 -0
- package/lib/browser/merge-editor/model/line-range.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/line-range.js +111 -0
- package/lib/browser/merge-editor/model/line-range.js.map +1 -0
- package/lib/browser/merge-editor/model/live-diff.d.ts +26 -0
- package/lib/browser/merge-editor/model/live-diff.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/live-diff.js +85 -0
- package/lib/browser/merge-editor/model/live-diff.js.map +1 -0
- package/lib/browser/merge-editor/model/merge-editor-model.d.ts +116 -0
- package/lib/browser/merge-editor/model/merge-editor-model.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/merge-editor-model.js +507 -0
- package/lib/browser/merge-editor/model/merge-editor-model.js.map +1 -0
- package/lib/browser/merge-editor/model/merge-range.d.ts +50 -0
- package/lib/browser/merge-editor/model/merge-range.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/merge-range.js +215 -0
- package/lib/browser/merge-editor/model/merge-range.js.map +1 -0
- package/lib/browser/merge-editor/model/range-editing.d.ts +21 -0
- package/lib/browser/merge-editor/model/range-editing.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/range-editing.js +68 -0
- package/lib/browser/merge-editor/model/range-editing.js.map +1 -0
- package/lib/browser/merge-editor/model/range-mapping.d.ts +106 -0
- package/lib/browser/merge-editor/model/range-mapping.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/range-mapping.js +252 -0
- package/lib/browser/merge-editor/model/range-mapping.js.map +1 -0
- package/lib/browser/merge-editor/model/range-mapping.spec.d.ts +2 -0
- package/lib/browser/merge-editor/model/range-mapping.spec.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/range-mapping.spec.js +48 -0
- package/lib/browser/merge-editor/model/range-mapping.spec.js.map +1 -0
- package/lib/browser/merge-editor/model/range-utils.d.ts +25 -0
- package/lib/browser/merge-editor/model/range-utils.d.ts.map +1 -0
- package/lib/browser/merge-editor/model/range-utils.js +118 -0
- package/lib/browser/merge-editor/model/range-utils.js.map +1 -0
- package/lib/browser/merge-editor/view/diff-spacers.d.ts +50 -0
- package/lib/browser/merge-editor/view/diff-spacers.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/diff-spacers.js +133 -0
- package/lib/browser/merge-editor/view/diff-spacers.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/index.d.ts +6 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/index.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/index.js +24 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/index.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-base-pane.d.ts +12 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-base-pane.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-base-pane.js +65 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-base-pane.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.d.ts +30 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.js +102 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane.d.ts +49 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane.js +214 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-result-pane.d.ts +16 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-result-pane.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-result-pane.js +107 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-result-pane.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-side-pane.d.ts +27 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-side-pane.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-side-pane.js +135 -0
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-side-pane.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-scroll-sync.d.ts +20 -0
- package/lib/browser/merge-editor/view/merge-editor-scroll-sync.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-scroll-sync.js +218 -0
- package/lib/browser/merge-editor/view/merge-editor-scroll-sync.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-view-zones.d.ts +57 -0
- package/lib/browser/merge-editor/view/merge-editor-view-zones.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-editor-view-zones.js +218 -0
- package/lib/browser/merge-editor/view/merge-editor-view-zones.js.map +1 -0
- package/lib/browser/merge-editor/view/merge-range-actions.d.ts +23 -0
- package/lib/browser/merge-editor/view/merge-range-actions.d.ts.map +1 -0
- package/lib/browser/merge-editor/view/merge-range-actions.js +142 -0
- package/lib/browser/merge-editor/view/merge-range-actions.js.map +1 -0
- package/lib/browser/scm-colors.d.ts +2 -0
- package/lib/browser/scm-colors.d.ts.map +1 -1
- package/lib/browser/scm-colors.js +2 -0
- package/lib/browser/scm-colors.js.map +1 -1
- package/lib/browser/scm-frontend-module.d.ts.map +1 -1
- package/lib/browser/scm-frontend-module.js +2 -0
- package/lib/browser/scm-frontend-module.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/decorations/scm-decorations-service.ts +18 -1
- package/src/browser/merge-editor/merge-editor-contribution.ts +346 -0
- package/src/browser/merge-editor/merge-editor-dev-contribution.ts +154 -0
- package/src/browser/merge-editor/merge-editor-module.ts +134 -0
- package/src/browser/merge-editor/merge-editor.ts +643 -0
- package/src/browser/merge-editor/model/line-range.ts +128 -0
- package/src/browser/merge-editor/model/live-diff.ts +111 -0
- package/src/browser/merge-editor/model/merge-editor-model.ts +623 -0
- package/src/browser/merge-editor/model/merge-range.ts +268 -0
- package/src/browser/merge-editor/model/range-editing.ts +81 -0
- package/src/browser/merge-editor/model/range-mapping.spec.ts +52 -0
- package/src/browser/merge-editor/model/range-mapping.ts +396 -0
- package/src/browser/merge-editor/model/range-utils.ts +115 -0
- package/src/browser/merge-editor/view/diff-spacers.ts +160 -0
- package/src/browser/merge-editor/view/merge-editor-panes/index.ts +21 -0
- package/src/browser/merge-editor/view/merge-editor-panes/merge-editor-base-pane.ts +71 -0
- package/src/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.tsx +106 -0
- package/src/browser/merge-editor/view/merge-editor-panes/merge-editor-pane.ts +246 -0
- package/src/browser/merge-editor/view/merge-editor-panes/merge-editor-result-pane.ts +115 -0
- package/src/browser/merge-editor/view/merge-editor-panes/merge-editor-side-pane.ts +139 -0
- package/src/browser/merge-editor/view/merge-editor-scroll-sync.ts +241 -0
- package/src/browser/merge-editor/view/merge-editor-view-zones.ts +264 -0
- package/src/browser/merge-editor/view/merge-range-actions.ts +159 -0
- package/src/browser/scm-colors.ts +2 -0
- package/src/browser/scm-frontend-module.ts +4 -0
- package/src/browser/style/merge-editor.css +221 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 1C-Soft LLC and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { nls } from '@theia/core';
|
|
19
|
+
import { Autorun } from '@theia/core/lib/common/observable';
|
|
20
|
+
import { EditorDecoration, Range } from '@theia/editor/lib/browser';
|
|
21
|
+
import { MergeEditorPane } from './merge-editor-pane';
|
|
22
|
+
import { MergeRange } from '../../model/merge-range';
|
|
23
|
+
import { LineRange } from '../../model/line-range';
|
|
24
|
+
|
|
25
|
+
@injectable()
|
|
26
|
+
export class MergeEditorBasePane extends MergeEditorPane {
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
super();
|
|
30
|
+
this.addClass('base');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override getLineRangeForMergeRange(mergeRange: MergeRange): LineRange {
|
|
34
|
+
return mergeRange.baseRange;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected override translateBaseRange(range: Range): Range {
|
|
38
|
+
return range;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected override onAfterMergeEditorSet(): void {
|
|
42
|
+
super.onAfterMergeEditorSet();
|
|
43
|
+
this.toDispose.push(Autorun.create(() => {
|
|
44
|
+
const { currentPane, side1Pane, side1Title, side2Pane, side2Title } = this.mergeEditor;
|
|
45
|
+
this.header.description = currentPane === this ? '' : nls.localizeByDefault('Comparing with {0}',
|
|
46
|
+
currentPane === side1Pane ? side1Title : currentPane === side2Pane ? side2Title : nls.localizeByDefault('Result')
|
|
47
|
+
);
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected override computeEditorDecorations(): EditorDecoration[] {
|
|
52
|
+
const result: EditorDecoration[] = [];
|
|
53
|
+
|
|
54
|
+
const { model, currentPane, side1Pane, side2Pane, currentMergeRange } = this.mergeEditor;
|
|
55
|
+
|
|
56
|
+
for (const mergeRange of model.mergeRanges) {
|
|
57
|
+
const lineRange = mergeRange.baseRange;
|
|
58
|
+
result.push(this.toMergeRangeDecoration(lineRange, {
|
|
59
|
+
isHandled: model.isMergeRangeHandled(mergeRange),
|
|
60
|
+
isFocused: mergeRange === currentMergeRange,
|
|
61
|
+
isAfterEnd: lineRange.startLineNumber > model.baseDocument.lineCount,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (currentPane !== this) {
|
|
66
|
+
const changes = currentPane === side1Pane ? model.side1Changes : currentPane === side2Pane ? model.side2Changes : model.resultChanges;
|
|
67
|
+
result.push(...this.toChangeDecorations(changes, { diffSide: 'original' }));
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 1C-Soft LLC and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import * as React from '@theia/core/shared/react';
|
|
19
|
+
import { codicon, Message, onDomEvent, ReactWidget } from '@theia/core/lib/browser';
|
|
20
|
+
import { LabelParser } from '@theia/core/lib/browser/label-parser';
|
|
21
|
+
|
|
22
|
+
@injectable()
|
|
23
|
+
export class MergeEditorPaneHeader extends ReactWidget {
|
|
24
|
+
|
|
25
|
+
@inject(LabelParser)
|
|
26
|
+
protected readonly labelParser: LabelParser;
|
|
27
|
+
|
|
28
|
+
private _description = '';
|
|
29
|
+
get description(): string {
|
|
30
|
+
return this._description;
|
|
31
|
+
}
|
|
32
|
+
set description(description: string) {
|
|
33
|
+
this._description = description;
|
|
34
|
+
this.update();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private _detail = '';
|
|
38
|
+
get detail(): string {
|
|
39
|
+
return this._detail;
|
|
40
|
+
}
|
|
41
|
+
set detail(detail: string) {
|
|
42
|
+
this._detail = detail;
|
|
43
|
+
this.update();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private _toolbarItems: readonly MergeEditorPaneToolbarItem[];
|
|
47
|
+
get toolbarItems(): readonly MergeEditorPaneToolbarItem[] {
|
|
48
|
+
return this._toolbarItems;
|
|
49
|
+
}
|
|
50
|
+
set toolbarItems(toolbarItems: readonly MergeEditorPaneToolbarItem[]) {
|
|
51
|
+
this._toolbarItems = toolbarItems;
|
|
52
|
+
this.update();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@postConstruct()
|
|
56
|
+
protected init(): void {
|
|
57
|
+
this.addClass('header');
|
|
58
|
+
this.scrollOptions = undefined;
|
|
59
|
+
this.node.tabIndex = -1;
|
|
60
|
+
this.toDispose.push(onDomEvent(this.node, 'click', () => this.activate()));
|
|
61
|
+
this.title.changed.connect(this.update, this);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected override onActivateRequest(msg: Message): void {
|
|
65
|
+
super.onActivateRequest(msg);
|
|
66
|
+
this.parent?.activate();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected override render(): React.ReactNode {
|
|
70
|
+
return (
|
|
71
|
+
<React.Fragment>
|
|
72
|
+
<span className='title'>{this.renderWithIcons(this.title.label)}</span>
|
|
73
|
+
<span className='description'>{this.renderWithIcons(this.description)}</span>
|
|
74
|
+
<span className='detail'>{this.renderWithIcons(this.detail)}</span>
|
|
75
|
+
<span className='toolbar' onClick={this.handleToolbarClick}>{this.toolbarItems.map(toolbarItem => this.renderToolbarItem(toolbarItem))}</span>
|
|
76
|
+
</React.Fragment>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private readonly handleToolbarClick = (event: React.MouseEvent) => event.nativeEvent.stopImmediatePropagation();
|
|
81
|
+
|
|
82
|
+
protected renderWithIcons(text: string): React.ReactNode[] {
|
|
83
|
+
const result: React.ReactNode[] = [];
|
|
84
|
+
const labelParts = this.labelParser.parse(text);
|
|
85
|
+
labelParts.forEach((labelPart, index) => {
|
|
86
|
+
if (typeof labelPart === 'string') {
|
|
87
|
+
result.push(labelPart);
|
|
88
|
+
} else {
|
|
89
|
+
result.push(<span key={index} className={codicon(labelPart.name)}></span>);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected renderToolbarItem({ id, label, tooltip, className, onClick }: MergeEditorPaneToolbarItem): React.ReactNode {
|
|
96
|
+
return <span key={id} title={tooltip} onClick={onClick} className={className}>{label}</span>;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface MergeEditorPaneToolbarItem {
|
|
101
|
+
readonly id: string;
|
|
102
|
+
readonly label?: string;
|
|
103
|
+
readonly tooltip?: string;
|
|
104
|
+
readonly className?: string;
|
|
105
|
+
readonly onClick?: (event: React.MouseEvent) => void;
|
|
106
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 1C-Soft LLC and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import { Disposable, DisposableCollection } from '@theia/core';
|
|
19
|
+
import { Autorun, DerivedObservable, Observable, ObservableFromEvent } from '@theia/core/lib/common/observable';
|
|
20
|
+
import { BoxPanel, Message } from '@theia/core/lib/browser';
|
|
21
|
+
import { EditorDecoration, EditorWidget, MinimapPosition, OverviewRulerLane, Position, Range, TrackedRangeStickiness } from '@theia/editor/lib/browser';
|
|
22
|
+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
23
|
+
import { MonacoToProtocolConverter } from '@theia/monaco/lib/browser/monaco-to-protocol-converter';
|
|
24
|
+
import { Selection } from '@theia/monaco-editor-core';
|
|
25
|
+
import { MergeEditorPaneHeader, MergeEditorPaneToolbarItem } from './merge-editor-pane-header';
|
|
26
|
+
import { MergeEditor } from '../../merge-editor';
|
|
27
|
+
import { MergeRange } from '../../model/merge-range';
|
|
28
|
+
import { DetailedLineRangeMapping } from '../../model/range-mapping';
|
|
29
|
+
import { LineRange } from '../../model/line-range';
|
|
30
|
+
import { RangeUtils } from '../../model/range-utils';
|
|
31
|
+
import { ScmColors } from '../../../scm-colors';
|
|
32
|
+
|
|
33
|
+
@injectable()
|
|
34
|
+
export abstract class MergeEditorPane extends BoxPanel {
|
|
35
|
+
|
|
36
|
+
@inject(MergeEditorPaneHeader)
|
|
37
|
+
readonly header: MergeEditorPaneHeader;
|
|
38
|
+
|
|
39
|
+
@inject(EditorWidget)
|
|
40
|
+
readonly editorWidget: EditorWidget;
|
|
41
|
+
|
|
42
|
+
@inject(MonacoToProtocolConverter)
|
|
43
|
+
private readonly m2p: MonacoToProtocolConverter;
|
|
44
|
+
|
|
45
|
+
get editor(): MonacoEditor {
|
|
46
|
+
return MonacoEditor.get(this.editorWidget)!;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected _mergeEditor: MergeEditor;
|
|
50
|
+
|
|
51
|
+
protected cursorPositionObservable: Observable<Position>;
|
|
52
|
+
protected cursorLineObservable: Observable<number>;
|
|
53
|
+
protected selectionObservable: Observable<Range[] | undefined>;
|
|
54
|
+
|
|
55
|
+
protected readonly toDispose = new DisposableCollection();
|
|
56
|
+
|
|
57
|
+
constructor() {
|
|
58
|
+
super({ spacing: 0 });
|
|
59
|
+
this.addClass('editor-pane');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@postConstruct()
|
|
63
|
+
protected init(): void {
|
|
64
|
+
this.cursorPositionObservable = ObservableFromEvent.create(this.editor.onCursorPositionChanged, () => this.editor.cursor);
|
|
65
|
+
this.cursorLineObservable = DerivedObservable.create(() => this.cursorPositionObservable.get().line);
|
|
66
|
+
this.selectionObservable = ObservableFromEvent.create(this.editor.getControl().onDidChangeCursorSelection, () => {
|
|
67
|
+
const selections = this.editor.getControl().getSelections();
|
|
68
|
+
return selections?.map(selection => this.m2p.asRange(selection));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
BoxPanel.setStretch(this.header, 0);
|
|
72
|
+
BoxPanel.setStretch(this.editorWidget, 1);
|
|
73
|
+
|
|
74
|
+
this.addWidget(this.header);
|
|
75
|
+
this.addWidget(this.editorWidget);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override dispose(): void {
|
|
79
|
+
super.dispose();
|
|
80
|
+
this.toDispose.dispose();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get mergeEditor(): MergeEditor {
|
|
84
|
+
return this._mergeEditor;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
set mergeEditor(mergeEditor: MergeEditor) {
|
|
88
|
+
if (this._mergeEditor) {
|
|
89
|
+
throw new Error('Merge editor has already been set');
|
|
90
|
+
}
|
|
91
|
+
this._mergeEditor = mergeEditor;
|
|
92
|
+
this.onAfterMergeEditorSet();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected onAfterMergeEditorSet(): void {
|
|
96
|
+
this.initContextKeys();
|
|
97
|
+
|
|
98
|
+
const toolbarItems = DerivedObservable.create(() => this.getToolbarItems());
|
|
99
|
+
this.toDispose.push(Autorun.create(() => {
|
|
100
|
+
this.header.toolbarItems = toolbarItems.get();
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
this.initSelectionSynchronizer();
|
|
104
|
+
|
|
105
|
+
let decorationIds: string[] = [];
|
|
106
|
+
const decorations = DerivedObservable.create(() => this.computeEditorDecorations());
|
|
107
|
+
const isVisible = ObservableFromEvent.create(this.editorWidget.onDidChangeVisibility, () => this.editorWidget.isVisible);
|
|
108
|
+
|
|
109
|
+
this.toDispose.push(Autorun.create(() => {
|
|
110
|
+
if (this.mergeEditor.isShown && isVisible.get()) {
|
|
111
|
+
decorationIds = this.editor.deltaDecorations({ oldDecorations: decorationIds, newDecorations: decorations.get() });
|
|
112
|
+
}
|
|
113
|
+
}));
|
|
114
|
+
this.toDispose.push(Disposable.create(() =>
|
|
115
|
+
decorationIds = this.editor.deltaDecorations({ oldDecorations: decorationIds, newDecorations: [] })
|
|
116
|
+
));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get cursorPosition(): Position {
|
|
120
|
+
return this.cursorPositionObservable.get();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
get cursorLine(): number {
|
|
124
|
+
return this.cursorLineObservable.get();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get selection(): Range[] | undefined {
|
|
128
|
+
return this.selectionObservable.get();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
goToMergeRange(mergeRange: MergeRange, options?: { reveal?: boolean }): void {
|
|
132
|
+
const { editor } = this;
|
|
133
|
+
const { startLineNumber, endLineNumberExclusive } = this.getLineRangeForMergeRange(mergeRange);
|
|
134
|
+
editor.cursor = { line: startLineNumber, character: 0 };
|
|
135
|
+
const reveal = options?.reveal ?? true;
|
|
136
|
+
if (reveal) {
|
|
137
|
+
editor.getControl().revealLinesNearTop(startLineNumber + 1, endLineNumberExclusive + 1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
abstract getLineRangeForMergeRange(mergeRange: MergeRange): LineRange;
|
|
142
|
+
|
|
143
|
+
protected abstract translateBaseRange(range: Range): Range;
|
|
144
|
+
|
|
145
|
+
protected getToolbarItems(): MergeEditorPaneToolbarItem[] {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
protected computeEditorDecorations(): EditorDecoration[] {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
protected toMergeRangeDecoration(lineRange: LineRange,
|
|
154
|
+
{ isHandled, isFocused, isAfterEnd }: { isHandled: boolean, isFocused: boolean, isAfterEnd: boolean }
|
|
155
|
+
): EditorDecoration {
|
|
156
|
+
const blockClassNames = ['merge-range'];
|
|
157
|
+
let blockPadding: [top: number, right: number, bottom: number, left: number] = [0, 0, 0, 0];
|
|
158
|
+
if (isHandled) {
|
|
159
|
+
blockClassNames.push('handled');
|
|
160
|
+
}
|
|
161
|
+
if (isFocused) {
|
|
162
|
+
blockClassNames.push('focused');
|
|
163
|
+
blockPadding = [0, 2, 0, 2];
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
range: lineRange.toInclusiveRangeOrEmpty(),
|
|
167
|
+
options: {
|
|
168
|
+
blockClassName: blockClassNames.join(' '),
|
|
169
|
+
blockPadding,
|
|
170
|
+
blockIsAfterEnd: isAfterEnd,
|
|
171
|
+
minimap: {
|
|
172
|
+
position: MinimapPosition.Gutter,
|
|
173
|
+
color: { id: isHandled ? ScmColors.handledConflictMinimapOverviewRulerColor : ScmColors.unhandledConflictMinimapOverviewRulerColor },
|
|
174
|
+
},
|
|
175
|
+
overviewRuler: {
|
|
176
|
+
position: OverviewRulerLane.Center,
|
|
177
|
+
color: { id: isHandled ? ScmColors.handledConflictMinimapOverviewRulerColor : ScmColors.unhandledConflictMinimapOverviewRulerColor },
|
|
178
|
+
},
|
|
179
|
+
showIfCollapsed: true,
|
|
180
|
+
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
protected toChangeDecorations(changes: readonly DetailedLineRangeMapping[],
|
|
186
|
+
{ diffSide }: { diffSide: 'original' | 'modified' }
|
|
187
|
+
): EditorDecoration[] {
|
|
188
|
+
const result: EditorDecoration[] = [];
|
|
189
|
+
for (const change of changes) {
|
|
190
|
+
const changeRange = (diffSide === 'original' ? change.originalRange : change.modifiedRange).toInclusiveRange();
|
|
191
|
+
if (changeRange) {
|
|
192
|
+
result.push({
|
|
193
|
+
range: changeRange,
|
|
194
|
+
options: {
|
|
195
|
+
className: 'diff',
|
|
196
|
+
isWholeLine: true,
|
|
197
|
+
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
for (const rangeMapping of change.rangeMappings) {
|
|
203
|
+
const range = diffSide === 'original' ? rangeMapping.originalRange : rangeMapping.modifiedRange;
|
|
204
|
+
result.push({
|
|
205
|
+
range,
|
|
206
|
+
options: {
|
|
207
|
+
className: RangeUtils.isEmpty(range) ? 'diff-empty-word' : 'diff-word',
|
|
208
|
+
showIfCollapsed: true,
|
|
209
|
+
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
protected initContextKeys(): void {
|
|
218
|
+
const editor = this.editor.getControl();
|
|
219
|
+
editor.createContextKey('isMergeEditor', true);
|
|
220
|
+
editor.createContextKey('mergeEditorBaseUri', this.mergeEditor.baseUri.toString());
|
|
221
|
+
editor.createContextKey('mergeEditorResultUri', this.mergeEditor.resultUri.toString());
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
protected initSelectionSynchronizer(): void {
|
|
225
|
+
const selectionObservable = DerivedObservable.create(() => {
|
|
226
|
+
const { selectionInBase, currentPane } = this.mergeEditor;
|
|
227
|
+
if (!selectionInBase || currentPane === this) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
return selectionInBase.map(range => this.translateBaseRange(range));
|
|
231
|
+
});
|
|
232
|
+
this.toDispose.push(Autorun.create(() => {
|
|
233
|
+
const selection = selectionObservable.get();
|
|
234
|
+
if (selection.length) {
|
|
235
|
+
this.editor.getControl().setSelections(selection.map(
|
|
236
|
+
({ start, end }) => new Selection(start.line + 1, start.character + 1, end.line + 1, end.character + 1)
|
|
237
|
+
));
|
|
238
|
+
}
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
protected override onActivateRequest(msg: Message): void {
|
|
243
|
+
super.onActivateRequest(msg);
|
|
244
|
+
this.editorWidget.activate();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 1C-Soft LLC and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { nls } from '@theia/core';
|
|
19
|
+
import { ACTION_ITEM, codicon, ConfirmDialog, Dialog, DISABLED_CLASS } from '@theia/core/lib/browser';
|
|
20
|
+
import { ObservableUtils } from '@theia/core/lib/common/observable';
|
|
21
|
+
import { EditorDecoration, Range } from '@theia/editor/lib/browser';
|
|
22
|
+
import { MergeEditorPane } from './merge-editor-pane';
|
|
23
|
+
import { MergeEditorPaneToolbarItem } from './merge-editor-pane-header';
|
|
24
|
+
import { LineRange } from '../../model/line-range';
|
|
25
|
+
import { MergeRange } from '../../model/merge-range';
|
|
26
|
+
|
|
27
|
+
@injectable()
|
|
28
|
+
export class MergeEditorResultPane extends MergeEditorPane {
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
super();
|
|
32
|
+
this.addClass('result');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected override initContextKeys(): void {
|
|
36
|
+
super.initContextKeys();
|
|
37
|
+
this.editor.getControl().createContextKey('isMergeResultEditor', true);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override getLineRangeForMergeRange(mergeRange: MergeRange): LineRange {
|
|
41
|
+
return this.mergeEditor.model.getLineRangeInResult(mergeRange);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected override translateBaseRange(range: Range): Range {
|
|
45
|
+
return this.mergeEditor.model.translateBaseRangeToResult(range);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected goToNextUnhandledMergeRange(): void {
|
|
49
|
+
this.mergeEditor.goToNextMergeRange(mergeRange => !this.mergeEditor.model.isMergeRangeHandled(mergeRange));
|
|
50
|
+
this.mergeEditor.activate();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
reset(): void {
|
|
54
|
+
new ConfirmDialog({
|
|
55
|
+
title: nls.localize('theia/scm/mergeEditor/resetConfirmationTitle', 'Do you really want to reset the merge result in this editor?'),
|
|
56
|
+
msg: nls.localize('theia/scm/mergeEditor/resetConfirmationMessage', 'This action cannot be undone.'),
|
|
57
|
+
ok: Dialog.YES,
|
|
58
|
+
cancel: Dialog.NO,
|
|
59
|
+
}).open().then(async confirmed => {
|
|
60
|
+
if (confirmed) {
|
|
61
|
+
this.activate();
|
|
62
|
+
const { model } = this.mergeEditor;
|
|
63
|
+
await model.reset();
|
|
64
|
+
await ObservableUtils.waitForState(model.isUpToDateObservable);
|
|
65
|
+
this.mergeEditor.goToFirstMergeRange(mergeRange => !model.isMergeRangeHandled(mergeRange));
|
|
66
|
+
}
|
|
67
|
+
}).catch(e => console.error(e));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected override getToolbarItems(): MergeEditorPaneToolbarItem[] {
|
|
71
|
+
const { model } = this.mergeEditor;
|
|
72
|
+
const { unhandledMergeRangesCount } = model;
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
id: 'nextConflict',
|
|
76
|
+
label: unhandledMergeRangesCount === 1 ?
|
|
77
|
+
nls.localizeByDefault('{0} Conflict Remaining', unhandledMergeRangesCount) :
|
|
78
|
+
nls.localizeByDefault('{0} Conflicts Remaining ', unhandledMergeRangesCount),
|
|
79
|
+
tooltip: unhandledMergeRangesCount ?
|
|
80
|
+
nls.localizeByDefault('Go to next conflict') :
|
|
81
|
+
nls.localizeByDefault('All conflicts handled, the merge can be completed now.'),
|
|
82
|
+
className: ACTION_ITEM + (unhandledMergeRangesCount ? '' : ' ' + DISABLED_CLASS),
|
|
83
|
+
onClick: unhandledMergeRangesCount ?
|
|
84
|
+
() => this.goToNextUnhandledMergeRange() :
|
|
85
|
+
undefined
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'reset',
|
|
89
|
+
tooltip: nls.localizeByDefault('Reset'),
|
|
90
|
+
className: codicon('discard', true),
|
|
91
|
+
onClick: () => this.reset()
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected override computeEditorDecorations(): EditorDecoration[] {
|
|
97
|
+
const result: EditorDecoration[] = [];
|
|
98
|
+
|
|
99
|
+
const { model, currentMergeRange } = this.mergeEditor;
|
|
100
|
+
|
|
101
|
+
for (const mergeRange of model.mergeRanges) {
|
|
102
|
+
if (mergeRange) {
|
|
103
|
+
const lineRange = model.getLineRangeInResult(mergeRange);
|
|
104
|
+
result.push(this.toMergeRangeDecoration(lineRange, {
|
|
105
|
+
isHandled: model.isMergeRangeHandled(mergeRange),
|
|
106
|
+
isFocused: mergeRange === currentMergeRange,
|
|
107
|
+
isAfterEnd: lineRange.startLineNumber > model.resultDocument.lineCount,
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
result.push(...this.toChangeDecorations(model.resultChanges, { diffSide: 'modified' }));
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 1C-Soft LLC and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { nls } from '@theia/core';
|
|
19
|
+
import { ObservableUtils } from '@theia/core/lib/common/observable';
|
|
20
|
+
import { codicon, DiffUris, LabelProvider, open, OpenerService } from '@theia/core/lib/browser';
|
|
21
|
+
import { EditorDecoration, EditorOpenerOptions, Range } from '@theia/editor/lib/browser';
|
|
22
|
+
import { MergeRange, MergeRangeAcceptedState, MergeSide } from '../../model/merge-range';
|
|
23
|
+
import { MergeEditorPane } from './merge-editor-pane';
|
|
24
|
+
import { MergeEditorPaneToolbarItem } from './merge-editor-pane-header';
|
|
25
|
+
import { LineRange } from '../../model/line-range';
|
|
26
|
+
|
|
27
|
+
@injectable()
|
|
28
|
+
export abstract class MergeEditorSidePane extends MergeEditorPane {
|
|
29
|
+
|
|
30
|
+
@inject(LabelProvider)
|
|
31
|
+
protected readonly labelProvider: LabelProvider;
|
|
32
|
+
|
|
33
|
+
@inject(OpenerService)
|
|
34
|
+
protected readonly openerService: OpenerService;
|
|
35
|
+
|
|
36
|
+
abstract get mergeSide(): MergeSide;
|
|
37
|
+
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
this.addClass('side');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override getLineRangeForMergeRange(mergeRange: MergeRange): LineRange {
|
|
44
|
+
return mergeRange.getModifiedRange(this.mergeSide);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected override translateBaseRange(range: Range): Range {
|
|
48
|
+
return this.mergeEditor.model.translateBaseRangeToSide(range, this.mergeSide);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async acceptAllChanges(): Promise<void> {
|
|
52
|
+
const { model, resultPane } = this.mergeEditor;
|
|
53
|
+
resultPane.activate();
|
|
54
|
+
const selections = resultPane.editor.getControl().getSelections();
|
|
55
|
+
for (const mergeRange of model.mergeRanges) {
|
|
56
|
+
await ObservableUtils.waitForState(model.isUpToDateObservable);
|
|
57
|
+
resultPane.goToMergeRange(mergeRange, { reveal: false });
|
|
58
|
+
let state = model.getMergeRangeResultState(mergeRange);
|
|
59
|
+
if (state === 'Unrecognized') {
|
|
60
|
+
state = 'Base';
|
|
61
|
+
}
|
|
62
|
+
model.applyMergeRangeAcceptedState(mergeRange, MergeRangeAcceptedState.addSide(state, this.mergeSide));
|
|
63
|
+
}
|
|
64
|
+
if (selections) {
|
|
65
|
+
resultPane.editor.getControl().setSelections(selections);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
compareWithBase(): void {
|
|
70
|
+
let label = this.labelProvider.getName(this.editor.uri);
|
|
71
|
+
if (label) {
|
|
72
|
+
label += ': ';
|
|
73
|
+
}
|
|
74
|
+
label += `${nls.localizeByDefault('Base')} ⟷ ${this.header.title.label}`;
|
|
75
|
+
const options: EditorOpenerOptions = { selection: { start: this.editor.cursor } };
|
|
76
|
+
open(this.openerService, DiffUris.encode(this.mergeEditor.baseUri, this.editor.uri, label), options).catch(e => {
|
|
77
|
+
console.error(e);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected override getToolbarItems(): MergeEditorPaneToolbarItem[] {
|
|
82
|
+
return [
|
|
83
|
+
{
|
|
84
|
+
id: 'acceptAllChanges',
|
|
85
|
+
tooltip: nls.localizeByDefault(this.mergeSide === 1 ? 'Accept All Changes from Left' : 'Accept All Changes from Right'),
|
|
86
|
+
className: codicon('check-all', true),
|
|
87
|
+
onClick: () => this.acceptAllChanges()
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'compareWithBase',
|
|
91
|
+
tooltip: nls.localizeByDefault('Compare With Base'),
|
|
92
|
+
className: codicon('compare-changes', true),
|
|
93
|
+
onClick: () => this.compareWithBase()
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected override computeEditorDecorations(): EditorDecoration[] {
|
|
99
|
+
const result: EditorDecoration[] = [];
|
|
100
|
+
|
|
101
|
+
const { model, currentMergeRange } = this.mergeEditor;
|
|
102
|
+
const document = this.mergeSide === 1 ? model.side1Document : model.side2Document;
|
|
103
|
+
|
|
104
|
+
for (const mergeRange of model.mergeRanges) {
|
|
105
|
+
const lineRange = mergeRange.getModifiedRange(this.mergeSide);
|
|
106
|
+
result.push(this.toMergeRangeDecoration(lineRange, {
|
|
107
|
+
isHandled: model.isMergeRangeHandled(mergeRange),
|
|
108
|
+
isFocused: mergeRange === currentMergeRange,
|
|
109
|
+
isAfterEnd: lineRange.startLineNumber > document.lineCount,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const changes = this.mergeSide === 1 ? model.side1Changes : model.side2Changes;
|
|
114
|
+
result.push(...this.toChangeDecorations(changes, { diffSide: 'modified' }));
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@injectable()
|
|
120
|
+
export class MergeEditorSide1Pane extends MergeEditorSidePane {
|
|
121
|
+
|
|
122
|
+
readonly mergeSide = 1;
|
|
123
|
+
|
|
124
|
+
constructor() {
|
|
125
|
+
super();
|
|
126
|
+
this.addClass('side1');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@injectable()
|
|
131
|
+
export class MergeEditorSide2Pane extends MergeEditorSidePane {
|
|
132
|
+
|
|
133
|
+
readonly mergeSide = 2;
|
|
134
|
+
|
|
135
|
+
constructor() {
|
|
136
|
+
super();
|
|
137
|
+
this.addClass('side2');
|
|
138
|
+
}
|
|
139
|
+
}
|