Merge "Improves visible tabs rendering"

This commit is contained in:
Andrew Bonventre
2016-08-25 20:19:45 +00:00
committed by Gerrit Code Review
4 changed files with 145 additions and 9 deletions

View File

@@ -77,6 +77,7 @@ limitations under the License.
_builder: Object, _builder: Object,
_groups: Array, _groups: Array,
_layers: Array, _layers: Array,
_showTabs: Boolean,
}, },
get diffElement() { get diffElement() {
@@ -92,6 +93,7 @@ limitations under the License.
this._layers = [ this._layers = [
this.$.syntaxLayer, this.$.syntaxLayer,
this._createIntralineLayer(), this._createIntralineLayer(),
this._createTabIndicatorLayer(),
this.$.rangeLayer, this.$.rangeLayer,
]; ];
@@ -102,6 +104,7 @@ limitations under the License.
render: function(comments, prefs) { render: function(comments, prefs) {
this.$.syntaxLayer.enabled = prefs.syntax_highlighting; this.$.syntaxLayer.enabled = prefs.syntax_highlighting;
this._showTabs = !!prefs.show_tabs;
// Stop the processor (if it's running). // Stop the processor (if it's running).
this.$.processor.cancel(); this.$.processor.cancel();
@@ -330,6 +333,31 @@ limitations under the License.
}; };
}, },
_createTabIndicatorLayer: function() {
var show = (function() { return this._showTabs; }).bind(this);
return {
addListener: function() {},
annotate: function(el, line) {
// If visible tabs are disabled, do nothing.
if (!show()) { return; }
// Find and annotate the locations of tabs.
var split = line.text.split('\t');
if (!split) { return; }
for (var i = 0, pos = 0; i < split.length - 1; i++) {
// Skip forward by the length of the content
pos += split[i].length;
GrAnnotation.annotateElement(el, pos, 1,
'style-scope gr-diff tab-indicator');
// Skip forward by one tab character.
pos++;
}
},
};
},
/** /**
* In pages with large diffs, creating the first comment thread can be * In pages with large diffs, creating the first comment thread can be
* slow because nested Polymer elements (particularly * slow because nested Polymer elements (particularly

View File

@@ -493,7 +493,7 @@
for (var i = 0; i < split.length - 1; i++) { for (var i = 0; i < split.length - 1; i++) {
offset += split[i].length; offset += split[i].length;
width = tabSize - (offset % tabSize); width = tabSize - (offset % tabSize);
result += split[i] + this._getTabWrapper(width, this._prefs.show_tabs); result += split[i] + this._getTabWrapper(width);
offset += width; offset += width;
} }
if (split.length) { if (split.length) {
@@ -503,7 +503,7 @@
return result; return result;
}; };
GrDiffBuilder.prototype._getTabWrapper = function(tabSize, showTabs) { GrDiffBuilder.prototype._getTabWrapper = function(tabSize) {
// Force this to be a number to prevent arbitrary injection. // Force this to be a number to prevent arbitrary injection.
tabSize = +tabSize; tabSize = +tabSize;
if (isNaN(tabSize)) { if (isNaN(tabSize)) {
@@ -511,9 +511,6 @@
} }
var str = '<span class="style-scope gr-diff tab '; var str = '<span class="style-scope gr-diff tab ';
if (showTabs) {
str += 'withIndicator';
}
str += '" style="'; str += '" style="';
// TODO(andybons): CSS tab-size is not supported in IE. // TODO(andybons): CSS tab-size is not supported in IE.
str += 'tab-size:' + tabSize + ';'; str += 'tab-size:' + tabSize + ';';

View File

@@ -414,6 +414,117 @@ limitations under the License.
}); });
}); });
suite('tab indicators', function() {
var sandbox;
var element;
var layer;
setup(function() {
sandbox = sinon.sandbox.create();
element = fixture('basic');
element._showTabs = true;
layer = element._createTabIndicatorLayer();
});
teardown(function() {
sandbox.restore();
});
test('does nothing with empty line', function() {
var line = {text: ''};
var el = document.createElement('div');
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.isFalse(annotateElementStub.called);
});
test('does nothing with no tabs', function() {
var str = 'lorem ipsum no tabs';
var line = {text: str};
var el = document.createElement('div');
el.textContent = str;
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.isFalse(annotateElementStub.called);
});
test('annotates tab at beginning', function() {
var str = '\tlorem upsum';
var line = {text: str};
var el = document.createElement('div');
el.textContent = str;
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.equal(annotateElementStub.callCount, 1);
var args = annotateElementStub.getCalls()[0].args;
assert.equal(args[0], el);
assert.equal(args[1], 0, 'offset of tab indicator');
assert.equal(args[2], 1, 'length of tab indicator');
assert.include(args[3], 'tab-indicator');
});
test('does not annotate when disabled', function() {
element._showTabs = false;
var str = '\tlorem upsum';
var line = {text: str};
var el = document.createElement('div');
el.textContent = str;
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.isFalse(annotateElementStub.called);
});
test('annotates multiple in beginning', function() {
var str = '\t\tlorem upsum';
var line = {text: str};
var el = document.createElement('div');
el.textContent = str;
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.equal(annotateElementStub.callCount, 2);
var args = annotateElementStub.getCalls()[0].args;
assert.equal(args[0], el);
assert.equal(args[1], 0, 'offset of tab indicator');
assert.equal(args[2], 1, 'length of tab indicator');
assert.include(args[3], 'tab-indicator');
args = annotateElementStub.getCalls()[1].args;
assert.equal(args[0], el);
assert.equal(args[1], 1, 'offset of tab indicator');
assert.equal(args[2], 1, 'length of tab indicator');
assert.include(args[3], 'tab-indicator');
});
test('annotates intermediate tabs', function() {
var str = 'lorem\tupsum';
var line = {text: str};
var el = document.createElement('div');
el.textContent = str;
var annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, line);
assert.equal(annotateElementStub.callCount, 1);
var args = annotateElementStub.getCalls()[0].args;
assert.equal(args[0], el);
assert.equal(args[1], 5, 'offset of tab indicator');
assert.equal(args[2], 1, 'length of tab indicator');
assert.include(args[3], 'tab-indicator');
});
});
suite('rendering', function() { suite('rendering', function() {
var content; var content;
var outputEl; var outputEl;

View File

@@ -152,11 +152,11 @@ limitations under the License.
} }
.tab { .tab {
display: inline-block; display: inline-block;
position: relative;
} }
.tab.withIndicator { .tab-indicator:before {
color: #D68E47; color: #C62828;
text-decoration: line-through; /* >> character */
content: '\00BB';
} }
</style> </style>
<style include="gr-theme-default"></style> <style include="gr-theme-default"></style>