update blame gutter

pull/495/head
nightwing 2018-04-12 22:33:33 +04:00
rodzic 74023713c7
commit 63b1a96b96
4 zmienionych plików z 135 dodań i 177 usunięć

Wyświetl plik

@ -7,7 +7,7 @@
position: absolute; position: absolute;
border-right: 1px solid black; border-right: 1px solid black;
} }
.ace_resizer_v:hover { .ace_resizer_v:hover,.ace_resizer_v.hover {
border-right-color: darkblue; border-right-color: darkblue;
} }
.ace_closeButton { .ace_closeButton {
@ -38,7 +38,9 @@
overflow: hidden !important; overflow: hidden !important;
padding: 0 8px; padding: 0 8px;
border-top-color: rgba(230, 230, 250, 0.24); border-top-color: rgba(230, 230, 250, 0.24);
font-family: arial font-family: arial;
position: absolute;
width: 100%;
} }
.ace_blame-cell.selected{ .ace_blame-cell.selected{
background: rgba(255, 237, 0, 0.31); background: rgba(255, 237, 0, 0.31);

Wyświetl plik

@ -180,6 +180,7 @@ var BlameGutter = function(editor, blameStr) {
this.onMouseout = this.onMouseout.bind(this); this.onMouseout = this.onMouseout.bind(this);
this.blameData = []; this.blameData = [];
this.$cache = [];
if (blameStr) if (blameStr)
this.setData(blameStr); this.setData(blameStr);
@ -202,32 +203,24 @@ var BlameGutter = function(editor, blameStr) {
editor.blameGutter = this; editor.blameGutter = this;
gutter.blameColumn = this; gutter.blameColumn = this;
this.element = dom.createElement("div"); this.element = dom.buildDom(["div", {
this.element.className = "ace_layer ace_blame-gutter-layer"; class: "ace_layer ace_blame-gutter-layer ace_gutter"
var parentEl = editor.renderer.$gutter; }], editor.container);
parentEl.appendChild(this.element); this.resizer = dom.buildDom(["div", { class: "ace_resizer_v" },
["div", { class: "ace_closeButton" }]
this.resizer = dom.createElement("div"); ], editor.container);
this.resizer.className = "ace_resizer_v"; this.closeButton = this.resizer.firstChild;
parentEl.appendChild(this.resizer);
this.closeButton = dom.createElement("div");
this.closeButton.className = "ace_closeButton";
this.resizer.appendChild(this.closeButton);
gutter.update = this.drawGutter;
this.editor.on("guttermousedown", this.onMousedown);
var gutterEl = this.editor.renderer.$gutter; gutter.on("afterRender", this.drawGutter);
event.addListener(gutterEl, "mousemove", this.onMousemove); this.element.addEventListener("mousedown", this.onMousedown);
event.addListener(gutterEl, "mouseout", this.onMouseout); this.resizer.addEventListener("mousedown", this.onMousedown);
gutter.element.style.width = ""; event.addListener(this.element, "mousemove", this.onMousemove);
this.resizer.style.right = "40px"; event.addListener(this.element, "mouseout", this.onMouseout);
this.element.style.width = "260px";
parentEl.style.width = "300px";
gutter.update(this.editor.renderer.layerConfig); this.resizer.style.left =
this.element.style.width = "220px";
editor.renderer.setMargin(0, 0, 220, 0);
}; };
this.detachFromEditor = function() { this.detachFromEditor = function() {
@ -235,26 +228,14 @@ var BlameGutter = function(editor, blameStr) {
var editor = this.editor; var editor = this.editor;
var gutter = editor.renderer.$gutterLayer; var gutter = editor.renderer.$gutterLayer;
gutter.$cells.length = 0; gutter.off("afterRender", this.drawGutter);
gutter.element.innerHTML = "";
delete gutter.update;
editor.blameGutter = gutter.blameColumn = this.editor = null; editor.blameGutter = gutter.blameColumn = this.editor = null;
editor.off("guttermousedown", this.onMousedown); editor.renderer.setMargin(0);
var gutterEl = editor.renderer.$gutter;
event.removeListener(gutterEl, "mousemove", this.onMousemove);
event.removeListener(gutterEl, "mouseout", this.onMouseout);
gutterEl.style.width = "";
if (this.element.parentNode) this.element.remove();
this.element.parentNode.removeChild(this.element); this.resizer.remove();
if (this.resizer.parentNode)
this.resizer.parentNode.removeChild(this.resizer);
gutter.update(editor.renderer.layerConfig);
}; };
this.setData = function(blameStr) { this.setData = function(blameStr) {
@ -279,156 +260,117 @@ var BlameGutter = function(editor, blameStr) {
this.attachToEditor(e.editor); this.attachToEditor(e.editor);
}; };
this.drawGutter = function(config) { this.drawGutter = function(e, gutter) {
this.$config = config; var container = gutter.blameColumn.element;
var blameData = gutter.blameColumn.blameData;
var selectedHash = gutter.blameColumn.selectedHash;
var blameEl = this.blameColumn.element; var cells = gutter.$lines.cells;
blameEl.style.marginTop = -config.offset + "px"; var cache = gutter.blameColumn.$cache;
var cacheIndex = 0;
var html = []; var offset = - getTop(gutter.element) + gutter.config.offset;
var i = config.firstRow;
var lastRow = config.lastRow; var commit;
var fold = this.session.getNextFoldLine(i); for (var i = 0; i < cells.length; i++) {
var foldStart = fold ? fold.start.row : Infinity; var cell = cells[i];
var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets; var row = cell.row;
var lineHeight = config.lineHeight; var data = blameData[row];
var blameData = this.blameColumn.blameData; if (!data && i == 0) {
var selectedText = this.selectedText; // find first row
var blameHtml = []; while (!blameData[row] && row > 0) row--;
var $blameIndex, lastBlameCellIndex = 0; data = blameData[row]
var blameCell; commit = {
row: row,
findBlameCell(i); cell: cell,
if (blameCell) data: data,
addBlameCell(blameCell.text, blameCell.title); };
else
addBlameCell("", "");
// adjust top margin of first cell to always keep it on screen
if (!blameData[i + 1]) {
blameHtml[$blameIndex] -= config.offset - 1;
blameHtml.splice($blameIndex + 1, 0, "px;margin-top:", config.offset - 1);
}
while (true) {
if (i > foldStart) {
i = fold.end.row + 1;
fold = this.session.getNextFoldLine(i, fold);
if (fold) {
foldStart = fold.start.row;
lastBlameCellIndex = fold.end.row;
} else {
foldStart = Infinity;
}
} }
if (i > lastRow)
break; if (!data)
continue;
html.push("<div class='ace_gutter-cell",
"' style='height:", lineHeight, "px;'>", (i + 1)); if (commit)
add(commit.data, commit.row, commit.cell, cell);
if (foldWidgets) {
var c = foldWidgets[i]; commit = {
// check if cached value is invalidated and we need to recompute row: row,
if (c == null) cell: cell,
c = foldWidgets[i] = this.session.getFoldWidget(i); data: data,
if (c) };
html.push(
"<span class='ace_fold-widget ace_", c,
c == "start" && i == foldStart && i < fold.end.row ? " ace_closed" : " ace_open",
"' style='height:", lineHeight, "px",
"'></span>"
);
}
var wrappedRowLength = this.session.getRowLength(i) - 1;
while (wrappedRowLength--) {
html.push("</div><div class='ace_gutter-cell' style='height:", lineHeight, "px'>\xA6");
}
html.push("</div>");
i++;
// html for blame column
findBlameCell(i);
if (blameCell)
addBlameCell(blameCell.text, blameCell.title);
else
blameHtml[$blameIndex] += this.session.getRowLength(i - 1) * lineHeight;
} }
if (commit.cell == cell)
this.element.innerHTML = html.join(""); add(commit.data, commit.row, commit.cell);
blameEl.innerHTML = blameHtml.join("");
this.element.style.height = config.minHeight + "px"; function add(data, row, firstCell, nextCell) {
var el = cache[cacheIndex++];
var gutterWidth = this.element.parentNode.offsetWidth; if (!el)
if (gutterWidth !== this.gutterWidth) { cache.push(el = dom.createElement("div"));
this.gutterWidth = gutterWidth; el.className = "ace_blame-cell " + (data.data.hash == selectedHash ? "selected" : "");
this._emit("changeGutterWidth", gutterWidth); el.index = row;
el.textContent = data.text + " " + data.title;
var top = getTop(firstCell.element) - offset;
var next = nextCell ? getTop(nextCell.element) - offset : gutter.config.height;
el.style.top = top + "px";
el.style.height = next - top + "px";
container.appendChild(el);
} }
function addBlameCell(text, title) { while (cacheIndex < cache.length) {
blameHtml.push( cache.pop().remove();
"<div class='ace_blame-cell ", text == selectedText ? "selected" : "", }
"' index='", lastBlameCellIndex - 1, "'",
"style='height:", lineHeight, "px'>", function getTop(element) {
text, " ", title, return parseInt(element.style.top);
"</div>"
);
$blameIndex = blameHtml.length - 6;
}
function findBlameCell(i) {
do {
blameCell = blameData[i];
} while (!blameCell && i-- > lastBlameCellIndex);
lastBlameCellIndex = i + 1;
} }
}; };
this.onMousedown = function(e) { this.onMousedown = function(e) {
var target = e.domEvent.target; var target = e.target;
if (target == this.closeButton) { if (target == this.closeButton) {
this.removeData(); this.removeData();
return e.stop(); return event.stopEvent(e);
} }
if (target == this.resizer) { if (target == this.resizer) {
var rect = this.editor.blameGutter.element.getBoundingClientRect(); var rect = this.editor.blameGutter.element.getBoundingClientRect();
var mouseHandler = this.editor.$mouseHandler; var mouseHandler = this.editor.$mouseHandler;
apf.plane.setCursor("ew-resize");
this.editor.blameGutter.resizer.classList.add("hover");
mouseHandler.resizeBlameGutter = function() { mouseHandler.resizeBlameGutter = function() {
var gutterWidth = this.x + 40 - rect.left; var gutterWidth = this.x - rect.left;
this.editor.renderer.$gutter.style.width = gutterWidth + "px"; this.editor.blameGutter.resizer.style.left =
this.editor.blameGutter.element.style.width = gutterWidth - 40 + "px"; this.editor.blameGutter.element.style.width = gutterWidth + "px";
this.editor.renderer.$gutterLayer._emit("changeGutterWidth", gutterWidth); this.editor.renderer.setMargin(0, 0, gutterWidth, 0);
}; };
mouseHandler.resizeBlameGutterEnd = function() {
apf.plane.unsetCursor();
this.editor.blameGutter.resizer.classList.remove("hover");
};
mouseHandler.setState("resizeBlameGutter");
mouseHandler.captureMouse(e, mouseHandler.resizeBlameGutter.bind(mouseHandler)); mouseHandler.captureMouse(e, mouseHandler.resizeBlameGutter.bind(mouseHandler));
return e.stop(); return event.stopEvent(e);
} }
if (dom.hasCssClass(target, "ace_blame-cell")) { if (dom.hasCssClass(target, "ace_blame-cell")) {
var gutter = this.editor.renderer.$gutterLayer; var gutter = this.editor.renderer.$gutterLayer;
var index = parseInt(target.getAttribute("index"), 10); var blameData = gutter.blameColumn.blameData;
var blameCell = gutter.blameColumn.blameData[index]; var blameCell = blameData[target.index];
if (!blameCell) if (!blameCell)
return e.stop(); return event.stopEvent(e);
gutter.selectedText = blameCell.text; gutter.blameColumn.selectedHash = blameCell.data.hash;
var ch = target.parentNode.children; this.editor.renderer.$loop.schedule(this.editor.renderer.CHANGE_GUTTER);
for (var i = ch.length; i--;) { return event.stopEvent(e);
var isSelected = ch[i].innerHTML.indexOf(gutter.selectedText) == 0;
ch[i].className = "ace_blame-cell" + (isSelected ? " selected" : "");
}
return e.stop();
} }
}; };
this.onMousemove = function(e) { this.onMousemove = function(e) {
var target = e.target; var target = e.target;
var container = e.currentTarget; var container = e.currentTarget;
return;
var tooltip = this.editor.tooltip; var tooltip = this.editor.tooltip;
if (this.$highlightedCell != target) { if (this.$highlightedCell != target) {
if (dom.hasCssClass(target, "ace_blame-cell")) { if (dom.hasCssClass(target, "ace_blame-cell")) {
@ -439,8 +381,8 @@ var BlameGutter = function(editor, blameStr) {
} }
if (this.$highlightedCell) { if (this.$highlightedCell) {
// tooltip.style.top = e.clientY + 10 + "px"; tooltip.style.top = e.clientY + 10 + "px";
// tooltip.style.left = e.clientX + 10 + "px"; tooltip.style.left = e.clientX + 10 + "px";
} else { } else {
this.onMouseout(); this.onMouseout();
return; return;
@ -453,13 +395,6 @@ var BlameGutter = function(editor, blameStr) {
}).call(BlameGutter.prototype); }).call(BlameGutter.prototype);
// app.vfs.execFile("git", {
// args: ["blame", "-p", "-w", "--", "server.js"]
// }, function(e, x) {
// console.log(bb=x.stdout);
// });
exports.annotate = function annotate(editor, blameStr) { exports.annotate = function annotate(editor, blameStr) {
return new BlameGutter(editor, blameStr); return new BlameGutter(editor, blameStr);
}; };

Wyświetl plik

@ -83,7 +83,7 @@ var Lines = function(element, canvasHeight) {
}; };
this.push = function(cell) { this.push = function(cell) {
if (cell.length) { if (Array.isArray(cell)) {
this.cells.push.apply(this.cells, cell); this.cells.push.apply(this.cells, cell);
var fragment = dom.createFragment(this.element); var fragment = dom.createFragment(this.element);
for (var i=0; i<cell.length; i++) { for (var i=0; i<cell.length; i++) {
@ -97,7 +97,7 @@ var Lines = function(element, canvasHeight) {
}; };
this.unshift = function(cell) { this.unshift = function(cell) {
if (cell.length) { if (Array.isArray(cell)) {
this.cells.unshift.apply(this.cells, cell); this.cells.unshift.apply(this.cells, cell);
var fragment = dom.createFragment(this.element); var fragment = dom.createFragment(this.element);
for (var i=0; i<cell.length; i++) { for (var i=0; i<cell.length; i++) {

Wyświetl plik

@ -160,6 +160,15 @@ var VirtualRenderer = function(container, theme) {
v: 0, v: 0,
h: 0 h: 0
}; };
this.margin = {
left: 0,
right: 0,
top: 0,
bottom: 0,
v: 0,
h: 0
};
this.$loop = new RenderLoop( this.$loop = new RenderLoop(
this.$renderChanges.bind(this), this.$renderChanges.bind(this),
@ -407,8 +416,8 @@ var VirtualRenderer = function(container, theme) {
this.gutterWidth = gutterWidth; this.gutterWidth = gutterWidth;
dom.setStyle(this.scrollBarH.element.style, "left", gutterWidth + "px"); dom.setStyle(this.scrollBarH.element.style, "left", gutterWidth + "px");
dom.setStyle(this.scroller.style, "left", gutterWidth + "px"); dom.setStyle(this.scroller.style, "left", gutterWidth + this.margin.left + "px");
size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth() - this.margin.h);
var right = this.scrollBarV.getWidth() + "px"; var right = this.scrollBarV.getWidth() + "px";
dom.setStyle(this.scrollBarH.element.style, "right", right); dom.setStyle(this.scrollBarH.element.style, "right", right);
@ -640,7 +649,7 @@ var VirtualRenderer = function(container, theme) {
if (posLeft > this.$size.scrollerWidth - w) if (posLeft > this.$size.scrollerWidth - w)
posLeft = this.$size.scrollerWidth - w; posLeft = this.$size.scrollerWidth - w;
posLeft += this.gutterWidth; posLeft += this.gutterWidth + this.margin.left;
dom.setStyle(style, "height", h + "px"); dom.setStyle(style, "height", h + "px");
dom.setStyle(style, "width", w + "px"); dom.setStyle(style, "width", w + "px");
dom.translate(this.textarea, Math.min(posLeft, this.$size.scrollerWidth - w), Math.min(posTop, this.$size.height - h)); dom.translate(this.textarea, Math.min(posLeft, this.$size.scrollerWidth - w), Math.min(posTop, this.$size.height - h));
@ -715,6 +724,18 @@ var VirtualRenderer = function(container, theme) {
this.session.setScrollTop(-sm.top); this.session.setScrollTop(-sm.top);
this.updateFull(); this.updateFull();
}; };
this.setMargin = function(top, bottom, left, right) {
var sm = this.margin;
sm.top = top|0;
sm.bottom = bottom|0;
sm.right = right|0;
sm.left = left|0;
sm.v = sm.top + sm.bottom;
sm.h = sm.left + sm.right;
this.$updateCachedSize(true, this.gutterWidth, this.$size.width, this.$size.height);
this.updateFull();
};
/** /**
* Returns whether the horizontal scrollbar is set to be always visible. * Returns whether the horizontal scrollbar is set to be always visible.
@ -827,7 +848,7 @@ var VirtualRenderer = function(container, theme) {
if (changes & this.CHANGE_H_SCROLL) if (changes & this.CHANGE_H_SCROLL)
this.$updateScrollBarH(); this.$updateScrollBarH();
dom.translate(this.$gutter, 0, -config.offset); dom.translate(this.$gutter, this.margin.left, -config.offset);
dom.translate(this.content, -this.scrollLeft, -config.offset); dom.translate(this.content, -this.scrollLeft, -config.offset);
var width = config.width + 2 * this.$padding + "px"; var width = config.width + 2 * this.$padding + "px";
@ -1415,7 +1436,7 @@ var VirtualRenderer = function(container, theme) {
if (this.$hasCssTransforms) { if (this.$hasCssTransforms) {
canvasPos = {top:0, left: 0}; canvasPos = {top:0, left: 0};
var p = this.$fontMetrics.transformCoordinates([x, y]); var p = this.$fontMetrics.transformCoordinates([x, y]);
x = p[1] - this.gutterWidth; x = p[1] - this.gutterWidth - this.margin.left;
y = p[0]; y = p[0];
} else { } else {
canvasPos = this.scroller.getBoundingClientRect(); canvasPos = this.scroller.getBoundingClientRect();
@ -1434,7 +1455,7 @@ var VirtualRenderer = function(container, theme) {
if (this.$hasCssTransforms) { if (this.$hasCssTransforms) {
canvasPos = {top:0, left: 0}; canvasPos = {top:0, left: 0};
var p = this.$fontMetrics.transformCoordinates([x, y]); var p = this.$fontMetrics.transformCoordinates([x, y]);
x = p[1] - this.gutterWidth; x = p[1] - this.gutterWidth - this.margin.left;
y = p[0]; y = p[0];
} else { } else {
canvasPos = this.scroller.getBoundingClientRect(); canvasPos = this.scroller.getBoundingClientRect();