blob: 1ae2dbc5667e79adf060f5bcbc3da339822996dd [file] [log] [blame]
<!-- The <grid-sk> custom element declaration.
Displays thumbnails in a 2-dimensional grid, also responds to mouseover events
on each image. The top row and the left most column are the thumbnails of the
sources, and the rest of the grid is filled in with the thumbnails of the
diffs of the images. The layout looks like:
W T T T
L D D D
L D D D
Where:
W = A white thumbnail to hold the space.
T = A source thumbnail along the top.
L = A source thumbnail along the left.
D = A diff thumbnail between the top and left source images.
Attributes:
value - A dictionary of the form:
{
rows: [img1, img2, ...]
columns: [imgA, imgB, ...]
cells: [
[diff1A, diff2A, ...],
[diff1B, diff2B, ...],
]
}
Where imgX looks like:
{
digest: "abc12..." // The image digest.
n: 12 // The number of times the image ocurs in the current tile.
}
And diffXY looks like:
{
numDiffPixels: 27, // Number of differing pixels.
pixelDiffPercent: 1.1, // Percent of differing pixels.
maxRGBADiffs: [254, 0, 0, 0], // Max diffs per RGBA channels.
diffImgUrl: "/img/abc-def.pgn" // URL of the diff image.
}
Events:
'diff-click' - Triggered when an image is clicked on.
e.detail contains the diffXY info associated with that thumbnail.
'diff-dblclick' - Triggered when an image is double-clicked.
e.detail contains the diffXY info associated with that thumbnail.
Methods:
selectRow(row) - will highlight the row image of the given row index.
selectCell(row, column) - will highlight the cell image for the given row
index.
clearSelection() - clears all selections.
-->
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="bower_components/paper-tooltip/paper-tooltip.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">
<dom-module id="grid-sk">
<template>
<style include="iron-flex iron-flex-alignment">
.imgWrapper {
border: solid 2px lightgray;
display: block;
}
img {
display: block;
max-width:64px;
max-height:64px;
width: auto;
height: auto;
}
.colHeader {
width: 64px;
display: block;
margin: 5px;
padding: 2px;
}
.emptyCell, .imgWrapper {
margin: 5px;
width: 64px;
}
.imgWrapper {
height: 64px;
}
.emptyCell {
border: solid 2px white;
}
.ttTable {
font-size: 12px;
color: white;
}
.sortedColsHeader {
margin: 0 5px 0 5px;
padding: 5px 1em 5px 1em;
}
.highlight {
border-color: red;
}
</style>
<div class="vertical layout">
<div class="horizontal layout end" id="colsContainer">
<div class="emptyCell"></div>
<template is="dom-repeat" items="{{_getColsWithHeaders(_value.columns)}}" as="col">
<div class="colHeader">{{_diffTitle(col.type)}}</div>
</template>
<template is="dom-if" if={{_hasNoHeaderCols(_value.columns)}}>
<div class="sortedColsHeader">
Sorted <iron-icon icon="icons:trending-flat"></iron-icon>
</div>
</template>
</div>
<div class="horizontal layout">
<div class="vertical layout" id="rowsContainer">
<template is="dom-repeat" items="{{_value.rows}}" as="row" index-as="rowIdx">
<div class="horizontal layout">
<div class="imgWrapper" id$="row-[[rowIdx]]">
<img src$="{{_imgHref(row.digest)}}" data-rowdigest="{{rowIdx}}">
<paper-tooltip>
<table class="ttTable" border="0" cellspacing="5" cellpadding="5">
<tr><th>N</th><td>{{row.n}}</td></tr>
<tr hidden$="[[!row.summary]]"><th>Test</th><td>{{row.test}}</td></tr>
<tr hidden$="[[!row.summary]]"><th>Pos</th><td>{{row.summary.pos}}</td></tr>
<tr hidden$="[[!row.summary]]"><th>Neg</th><td>{{row.summary.neg}}</td></tr>
<tr hidden$="[[!row.summary]]"><th>Unt</th><td>{{row.summary.untriaged}}</td></tr>
</table>
</paper-tooltip>
</div>
<template is="dom-repeat" items="{{row.values}}" as="cell" index-as="colIdx">
<div class="imgWrapper" id$="cell-[[rowIdx]]-[[colIdx]]">
<img src$="{{_diffHref(row, cell)}}" data-row="{{rowIdx}}" data-col="{{colIdx}}">
<paper-tooltip>
<table class="ttTable" border="0" cellspacing="5" cellpadding="5">
<tr><th>Diff</th><td>{{cell.diffs.combined}}</td></tr>
<tr><th>Pixel Diff (%)</th><td>{{cell.pixelDiffPercent}}</td></tr>
<tr><th>Num Diff Pixels</th><td>{{cell.numDiffPixels}}</td></tr>
<tr><th>Max RBBA Diffs</th><td>[{{cell.maxRGBADiffs}}]</td></tr>
<tr><th>N</th><td>[{{cell.n}}]</td></tr>
</table>
</paper-tooltip>
</div>
</template>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
(function () {
Polymer({
is: 'grid-sk',
properties: {
_value: {
type: Object,
value: function() { return {}; }
}
},
ready: function () {
this.listen(this.$.rowsContainer, 'click', "_handleCellsClick");
this.listen(this.$.rowsContainer, 'dblclick', "_handleCellsDblClick");
this.clearSelection();
},
_handleCellsClick: function(ev) {
this._fireDiffEvent('diff-click', ev);
},
_handleCellsDblClick: function(ev) {
this._fireDiffEvent('diff-dblclick', ev);
},
_fireDiffEvent(evType, ev) {
if (ev.target.tagName === 'IMG') {
ev.stopPropagation();
if (this._deferredFire) {
this.cancelAsync(this._deferredFire);
this._deferredFire = null;
}
if ((ev.type === 'click') && (ev.detail > 1)) {
return;
}
// Fire the event, potentially with a delay.
var rowDigest = ev.target.dataRowdigest,
row = ev.target.dataRow,
col = ev.target.dataCol;
var detail = null;
if (rowDigest !== undefined) {
row = rowDigest;
detail = sk.object.shallowCopy(this._value.rows[row]);
delete(detail, 'values');
} else if ((row !== undefined) && (col !== undefined)) {
detail = sk.object.shallowCopy(this._value.rows[row].values[col]);
detail.colDigest = this._value.rows[row].values[col].digest;
}
if (!detail) {
return;
}
detail.rowDigest = this._value.rows[row].digest;
detail.test = this._value.rows[row].test;
detail.rowIndex = row;
detail.columnIndex = col;
var delay = (ev.type === 'click') ? 500 : 0;
this._deferredFire = this.async(function() {
this.fire(evType, detail);
this._deferredFire = null;
}.bind(this), delay);
}
},
setValue: function (value) {
this.set("_value", value);
},
_highlightClear: function(selector, clear) {
var ele = this.$$(selector);
if (ele) {
this.toggleClass('highlight', !clear, ele);
return true;
}
return false;
},
selectCell: function(row, column) {
if (this._highlightClear('#cell-'+ row + '-' + column, false)) {
this._selectedCellRow = row;
this._selectedCellCol = column;
}
},
selectRow: function(row) {
if (this._highlightClear('#row-'+ row, false)) {
this._selectedRow = row;
}
},
clearSelection: function() {
if (this._selectedCellRow >= 0) {
this._highlightClear('#cell-'+ this._selectedCellRow + '-' + this._selectedCellCol, true);
}
if (this._selectedRow >= 0) {
this._highlightClear('#row-'+ this._selectedRow, true);
}
this._selectedCellRow = -1;
this._selectedCellCol = -1;
this._selectedRow = -1;
},
_getColsWithHeaders: function(cols) {
if (!cols) {
return [];
}
var ret = [];
for(var i=0, ilen=cols.length; i<ilen; i++) {
if (this._diffTitle(cols[i].type)) {
ret.push(cols[i]);
} else {
return ret;
}
}
return ret;
},
_hasNoHeaderCols: function(cols) {
if (!cols) {
return false;
}
var withHeaders = this._getColsWithHeaders(cols);
return (withHeaders.length < cols.length);
},
_diffHref: function(row, cell) {
return gold.diffImgHref(row.digest, cell.digest);
},
_imgHref: gold.imgHref,
_diffTitle: gold.getDiffTitle
});
}());
</script>
</dom-module>