diff --git a/devtools/server/actors/highlighters/css-grid.js b/devtools/server/actors/highlighters/css-grid.js index e94c1d571323..c6b5b6e64250 100644 --- a/devtools/server/actors/highlighters/css-grid.js +++ b/devtools/server/actors/highlighters/css-grid.js @@ -14,8 +14,22 @@ const { const Services = require("Services"); const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled"; -const LINE_DASH_ARRAY = [5, 3]; -const LINE_STROKE_STYLE = "#483D88"; +const ROWS = "rows"; +const COLUMNS = "cols"; +const GRID_LINES_PROPERTIES = { + "edge": { + lineDash: [0, 0], + strokeStyle: "#4B0082" + }, + "explicit": { + lineDash: [5, 3], + strokeStyle: "#8A2BE2" + }, + "implicit": { + lineDash: [2, 2], + strokeStyle: "#9370DB" + } +}; /** * The CssGridHighlighter is the class that overlays a visual grid on top of @@ -172,70 +186,122 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, { return fragment.cols.lines[fragment.cols.lines.length - 1].start; }, - renderColLines(cols, {bounds}, startRowPos, endRowPos) { - let y1 = (bounds.top / getCurrentZoom(this.win)) + startRowPos; - let y2 = (bounds.top / getCurrentZoom(this.win)) + endRowPos; + /** + * Get the GridLine index of the last edge of the explicit grid for a grid dimension. + * + * @param {GridTracks} tracks + * The grid track of a given grid dimension. + * @return {Number} index of the last edge of the explicit grid for a grid dimension. + */ + getLastEdgeLineIndex(tracks) { + let trackIndex = tracks.length - 1; - if (this.options.infiniteLines) { - y1 = 0; - y2 = parseInt(this.canvas.getAttribute("height"), 10); + // Traverse the grid track backwards until we find an explicit track. + while (trackIndex >= 0 && tracks[trackIndex].type != "explicit") { + trackIndex--; } - for (let i = 0; i < cols.lines.length; i++) { - let line = cols.lines[i]; - let x = (bounds.left / getCurrentZoom(this.win)) + line.start; - this.renderLine(x, y1, x, y2); - - // Render a second line to illustrate the gutter for non-zero breadth. - if (line.breadth > 0) { - x = x + line.breadth; - this.renderLine(x, y1, x, y2); - } - } - }, - - renderRowLines(rows, {bounds}, startColPos, endColPos) { - let x1 = (bounds.left / getCurrentZoom(this.win)) + startColPos; - let x2 = (bounds.left / getCurrentZoom(this.win)) + endColPos; - - if (this.options.infiniteLines) { - x1 = 0; - x2 = parseInt(this.canvas.getAttribute("width"), 10); - } - - for (let i = 0; i < rows.lines.length; i++) { - let line = rows.lines[i]; - let y = (bounds.top / getCurrentZoom(this.win)) + line.start; - this.renderLine(x1, y, x2, y); - - // Render a second line to illustrate the gutter for non-zero breadth. - if (line.breadth > 0) { - y = y + line.breadth; - this.renderLine(x1, y, x2, y); - } - } - }, - - renderLine(x1, y1, x2, y2) { - this.ctx.save(); - this.ctx.setLineDash(LINE_DASH_ARRAY); - this.ctx.beginPath(); - this.ctx.translate(.5, .5); - this.ctx.moveTo(x1, y1); - this.ctx.lineTo(x2, y2); - this.ctx.strokeStyle = LINE_STROKE_STYLE; - this.ctx.stroke(); - this.ctx.restore(); + // The grid line index is the grid track index + 1. + return trackIndex + 1; }, renderFragment(fragment, quad) { - this.renderColLines(fragment.cols, quad, - this.getFirstRowLinePos(fragment), - this.getLastRowLinePos(fragment)); + this.renderLines(fragment.cols, quad, COLUMNS, "left", "top", "height", + this.getFirstRowLinePos(fragment), + this.getLastRowLinePos(fragment)); + this.renderLines(fragment.rows, quad, ROWS, "top", "left", "width", + this.getFirstColLinePos(fragment), + this.getLastColLinePos(fragment)); + }, - this.renderRowLines(fragment.rows, quad, - this.getFirstColLinePos(fragment), - this.getLastColLinePos(fragment)); + /** + * Render the grid lines given the grid dimension information of the + * column or row lines. + * + * @param {GridDimension} gridDimension + * Column or row grid dimension object. + * @param {Object} quad.bounds + * The content bounds of the box model region quads. + * @param {String} dimensionType + * The grid dimension type which is either the constant COLUMNS or ROWS. + * @param {String} mainSide + * The main side of the given grid dimension - "top" for rows and + * "left" for columns. + * @param {String} crossSide + * The cross side of the given grid dimension - "left" for rows and + * "top" for columns. + * @param {String} mainSize + * The main size of the given grid dimension - "width" for rows and + * "height" for columns. + * @param {Number} startPos + * The start position of the cross side of the grid dimension. + * @param {Number} endPos + * The end position of the cross side of the grid dimension. + */ + renderLines(gridDimension, {bounds}, dimensionType, mainSide, crossSide, + mainSize, startPos, endPos) { + let lineStartPos = (bounds[crossSide] / getCurrentZoom(this.win)) + startPos; + let lineEndPos = (bounds[crossSide] / getCurrentZoom(this.win)) + endPos; + + if (this.options.infiniteLines) { + lineStartPos = 0; + lineEndPos = parseInt(this.canvas.getAttribute(mainSize), 10); + } + + let lastEdgeLineIndex = this.getLastEdgeLineIndex(gridDimension.tracks); + + for (let i = 0; i < gridDimension.lines.length; i++) { + let line = gridDimension.lines[i]; + let linePos = (bounds[mainSide] / getCurrentZoom(this.win)) + line.start; + + if (i == 0 || i == lastEdgeLineIndex) { + this.renderLine(linePos, lineStartPos, lineEndPos, dimensionType, "edge"); + } else { + this.renderLine(linePos, lineStartPos, lineEndPos, dimensionType, + gridDimension.tracks[i - 1].type); + } + + // Render a second line to illustrate the gutter for non-zero breadth. + if (line.breadth > 0) { + linePos = linePos + line.breadth; + this.renderLine(linePos, lineStartPos, lineEndPos, dimensionType, + gridDimension.tracks[i].type); + } + } + }, + + /** + * Render the grid line on the css grid highlighter canvas. + * + * @param {Number} linePos + * The line position along the x-axis for a column grid line and + * y-axis for a row grid line. + * @param {Number} startPos + * The start position of the cross side of the grid line. + * @param {Number} endPos + * The end position of the cross side of the grid line. + * @param {String} dimensionType + * The grid dimension type which is either the constant COLUMNS or ROWS. + * @param {[type]} lineType + * The grid line type - "edge", "explicit", or "implicit". + */ + renderLine(linePos, startPos, endPos, dimensionType, lineType) { + this.ctx.save(); + this.ctx.setLineDash(GRID_LINES_PROPERTIES[lineType].lineDash); + this.ctx.beginPath(); + this.ctx.translate(.5, .5); + + if (dimensionType == COLUMNS) { + this.ctx.moveTo(linePos, startPos); + this.ctx.lineTo(linePos, endPos); + } else { + this.ctx.moveTo(startPos, linePos); + this.ctx.lineTo(endPos, linePos); + } + + this.ctx.strokeStyle = GRID_LINES_PROPERTIES[lineType].strokeStyle; + this.ctx.stroke(); + this.ctx.restore(); }, _hide() {