Skip to content
111 changes: 105 additions & 6 deletions src/ext/diff/base_diff_view.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
"use strict";

var oop = require("../../lib/oop");

Check warning on line 3 in src/ext/diff/base_diff_view.js

View workflow job for this annotation

GitHub Actions / build (16.x)

'oop' is assigned a value but never used
var Range = require("../../range").Range;
var dom = require("../../lib/dom");
var config = require("../../config");
var LineWidgets = require("../../line_widgets").LineWidgets;
var ScrollDiffDecorator = require("./scroll_diff_decorator").ScrollDiffDecorator;

// @ts-ignore
var css = require("./styles-css.js").cssText;

var Editor = require("../../editor").Editor;
var Renderer = require("../../virtual_renderer").VirtualRenderer;
var UndoManager = require("../../undomanager").UndoManager;
var Decorator = require("../../layer/decorators").Decorator;

require("../../theme/textmate");
// enable multiselect
require("../../multi_select");
Expand Down Expand Up @@ -125,6 +128,8 @@
diffModel.valueB || "")),
chunks: []
});

this.setupScrollbars();
}

addGutterDecorators() {
Expand All @@ -141,7 +146,6 @@
$setupModel(session, value) {
var editor = new Editor(new Renderer(), session);
editor.session.setUndoManager(new UndoManager());
// editor.renderer.setOption("decoratorType", "diff");
if (value) {
editor.setValue(value, -1);
}
Expand Down Expand Up @@ -290,13 +294,100 @@
this.editorA && this.editorA.renderer.updateBackMarkers();
this.editorB && this.editorB.renderer.updateBackMarkers();

//this.updateScrollBarDecorators();
setTimeout(() => {
this.updateScrollBarDecorators();
}, 0);

if (this.$foldUnchangedOnInput) {
this.foldUnchanged();
}
}

setupScrollbars() {
/**
* @param {Renderer & {$scrollDecorator: ScrollDiffDecorator}} renderer
*/
const setupScrollBar = (renderer) => {
setTimeout(() => {
this.$setScrollBarDecorators(renderer);
this.updateScrollBarDecorators();
}, 0);
};

if (this.inlineDiffEditor) {
setupScrollBar(this.activeEditor.renderer);
}
else {
setupScrollBar(this.editorA.renderer);
setupScrollBar(this.editorB.renderer);
}

}

$setScrollBarDecorators(renderer) {
if (renderer.$scrollDecorator) {
renderer.$scrollDecorator.destroy();
}
renderer.$scrollDecorator = new ScrollDiffDecorator(renderer.scrollBarV, renderer, this.inlineDiffEditor);
renderer.$scrollDecorator.setSessions(this.sessionA, this.sessionB);
renderer.scrollBarV.setVisible(true);
renderer.scrollBarV.element.style.bottom = renderer.scrollBarH.getHeight() + "px";
}

$resetDecorators(renderer) {
if (renderer.$scrollDecorator) {
renderer.$scrollDecorator.destroy();
}
renderer.$scrollDecorator = new Decorator(renderer.scrollBarV, renderer);
}

updateScrollBarDecorators() {
if (this.inlineDiffEditor) {
if (!this.activeEditor) {
return;

Check warning on line 347 in src/ext/diff/base_diff_view.js

View check run for this annotation

Codecov / codecov/patch

src/ext/diff/base_diff_view.js#L347

Added line #L347 was not covered by tests
}
this.activeEditor.renderer.$scrollDecorator.zones = [];
}
else {
if (!this.editorA || !this.editorB) {
return;
}
this.editorA.renderer.$scrollDecorator.zones = [];
this.editorB.renderer.$scrollDecorator.zones = [];
}

/**
* @param {DiffChunk} change
*/
const updateDecorators = (editor, change) => {
if (!editor) {
return;

Check warning on line 364 in src/ext/diff/base_diff_view.js

View check run for this annotation

Codecov / codecov/patch

src/ext/diff/base_diff_view.js#L364

Added line #L364 was not covered by tests
}
if (change.old.start.row != change.old.end.row) {
editor.renderer.$scrollDecorator.addZone(change.old.start.row, change.old.end.row - 1, "delete");
}
if (change.new.start.row != change.new.end.row) {
editor.renderer.$scrollDecorator.addZone(change.new.start.row, change.new.end.row - 1, "insert");
}
};

if (this.inlineDiffEditor) {
this.chunks && this.chunks.forEach((lineChange) => {
updateDecorators(this.activeEditor, lineChange);
});
this.activeEditor.renderer.$scrollDecorator.$updateDecorators(this.activeEditor.renderer.layerConfig);
}
else {
this.chunks && this.chunks.forEach((lineChange) => {
updateDecorators(this.editorA, lineChange);
updateDecorators(this.editorB, lineChange);
});

this.editorA.renderer.$scrollDecorator.$updateDecorators(this.editorA.renderer.layerConfig);
this.editorB.renderer.$scrollDecorator.$updateDecorators(this.editorB.renderer.layerConfig);
}
}

/**
*
* @param {string[]} val1
Expand Down Expand Up @@ -366,7 +457,7 @@
return row;
}

/**
/**
* scroll locking
* @abstract
**/
Expand Down Expand Up @@ -468,8 +559,8 @@
}
}
}
scheduleRealign() {

scheduleRealign() {
if (!this.realignPending) {
this.realignPending = true;
this.editorA.renderer.on("beforeRender", this.realign);
Expand Down Expand Up @@ -500,6 +591,14 @@
this.gutterDecoratorB && this.gutterDecoratorB.dispose();
this.sessionA.selection.clearSelection();
this.sessionB.selection.clearSelection();

if (this.savedOptionsA && this.savedOptionsA.customScrollbar) {
this.$resetDecorators(this.editorA.renderer);
}
if (this.savedOptionsB &&this.savedOptionsB.customScrollbar) {
this.$resetDecorators(this.editorB.renderer);

Check warning on line 599 in src/ext/diff/base_diff_view.js

View check run for this annotation

Codecov / codecov/patch

src/ext/diff/base_diff_view.js#L599

Added line #L599 was not covered by tests
}

this.editorA = this.editorB = null;

}
Expand Down Expand Up @@ -771,7 +870,7 @@
return this.editorA.getTheme();
}
},
});
});

var emptyGutterRenderer = {
getText: function name(params) {
Expand Down
80 changes: 76 additions & 4 deletions src/ext/diff/diff_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
var ace = require("../../ace");
var Range = require("../../range").Range;
var editorA, editorB, diffView;
const {Decorator} = require("../../layer/decorators");
const {ScrollDiffDecorator} = require("./scroll_diff_decorator");


var DEBUG = false;

Expand All @@ -28,14 +31,14 @@

function getValueA(lines) {
return lines.map(function(v) {
return v[0];
return v[0];
}).filter(function(x) {
return x != null;
}).join("\n");
}
function getValueB(lines) {
return lines.map(function(v) {
return v.length == 2 ? v[1] : v[0];
return v.length == 2 ? v[1] : v[0];
}).filter(function(x) {
return x != null;
}).join("\n");
Expand Down Expand Up @@ -191,7 +194,7 @@

diffView.setTheme("ace/theme/cloud_editor");
assert.equal(diffView.editorA.getTheme(), "ace/theme/cloud_editor");
assert.equal(diffView.editorB.getTheme(), "ace/theme/cloud_editor");
assert.equal(diffView.editorB.getTheme(), "ace/theme/cloud_editor");

diffView.editorB.setTheme("ace/theme/textmate");
assert.equal(diffView.editorA.getTheme(), "ace/theme/textmate");
Expand All @@ -212,7 +215,7 @@

diffView.detach();
checkEventRegistry();

},
"test: diff at ends": function() {
var diffProvider = new DiffProvider();
Expand Down Expand Up @@ -353,6 +356,7 @@

editorA.session.setValue(getValueA(simpleDiff));
editorB.session.setValue(getValueB(simpleDiff));
editorA.setOption("customScrollbar", true);

diffView = new InlineDiffView({
editorA, editorB,
Expand All @@ -378,6 +382,8 @@

assert.ok(!!diffView.editorB.renderer.$gutterLayer.$renderer);

assert.ok(editorA.renderer.$scrollDecorator instanceof ScrollDiffDecorator);

diffView.detach();

assert.equal(editorA.getOption("wrap"), "free");
Expand All @@ -388,9 +394,75 @@
assert.equal(editorB.getOption("fadeFoldWidgets"), false);
assert.equal(editorB.getOption("showFoldWidgets"), true);
assert.ok(!editorB.renderer.$gutterLayer.$renderer);

assert.ok(editorA.renderer.$scrollDecorator instanceof Decorator);
},
"test split diff scroll decorators": function(done) {
editorA.session.setValue(["a", "b", "c"].join("\n"));
editorB.session.setValue(["a", "c", "X"].join("\n"));

diffView = new DiffView({ editorA, editorB });
diffView.setProvider(new DiffProvider());
diffView.onInput();


editorA.renderer.$loop._flush();
editorB.renderer.$loop._flush();

setTimeout(() => {
assertDecoratorsPlacement(editorA, false);
done();
}, 0);
},
"test inline diff scroll decorators": function(done) {
editorA.session.setValue(["a", "b", "c"].join("\n"));
editorB.session.setValue(["a", "c", "X"].join("\n"));

diffView = new InlineDiffView({ editorA, editorB, showSideA: true });
diffView.setProvider(new DiffProvider());
diffView.onInput();

editorA.renderer.$loop._flush();

setTimeout(() => {
assertDecoratorsPlacement(editorA, true);
done();
}, 0);
}
};

function findPointFillStyle(imageData, y) {
const data = imageData.slice(4 * y, 4 * (y + 1));
const a = Math.round(data[3] / 256 * 100);
if (a === 100) return "rgb(" + data.slice(0, 3).join(",") + ")";
return "rgba(" + data.slice(0, 3).join(",") + "," + (a / 100) + ")";

Check warning on line 438 in src/ext/diff/diff_test.js

View check run for this annotation

Codecov / codecov/patch

src/ext/diff/diff_test.js#L438

Added line #L438 was not covered by tests
}

function assertDecoratorsPlacement(editor, inlineDiff) {
const decoA = editor.renderer.$scrollDecorator;
const ctxA = decoA.canvas.getContext("2d");
const delRow = 1;
const offA = decoA.sessionA.documentToScreenRow(delRow, 0) * decoA.lineHeight;
const centerA = offA + decoA.lineHeight / 2;
const yA = Math.round(decoA.heightRatio * centerA);
let imgA = ctxA.getImageData(decoA.oneZoneWidth, 0, 1, decoA.canvasHeight).data;
assert.equal(findPointFillStyle(imgA, yA), decoA.colors.light.delete);

if (inlineDiff) {
//make sure that in inline diff, markers fills the whole line (except error decorators part)
imgA = ctxA.getImageData(decoA.canvasWidth - 1, 0, 1, decoA.canvasHeight).data;
assert.equal(findPointFillStyle(imgA, yA), decoA.colors.light.delete);
}

const xB = decoA.oneZoneWidth * 2;
const imgB = ctxA.getImageData(xB, 0, 1, decoA.canvasHeight).data;

const insRow = 2;
const offB = decoA.sessionB.documentToScreenRow(insRow, 0) * decoA.lineHeight;
const centerB = offB + decoA.lineHeight / 2;
const yB = Math.round(decoA.heightRatio * centerB);
assert.equal(findPointFillStyle(imgB, yB), decoA.colors.light.insert);
}

if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
Expand Down
1 change: 1 addition & 0 deletions src/ext/diff/providers/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -2462,6 +2462,7 @@ var {DiffChunk} = require("../base_diff_view");
/**
* VSCode’s computeDiff provider
*/

class DiffProvider {
compute(originalLines, modifiedLines, opts) {
if (!opts) opts = {};
Expand Down
Loading