author | Gabriel Luong <gabriel.luong@gmail.com> |
Wed, 01 Mar 2017 02:46:50 -0500 | |
changeset 345341 | 51bf67737ecb58976dcbe96d0771f28268a0ee5d |
parent 345340 | b8a79ad3b03e21a21477d1d03311e623e277680d |
child 345342 | be8abf34c44948dd81253137ab52fd445b09e141 |
push id | 87564 |
push user | gabriel.luong@gmail.com |
push date | Wed, 01 Mar 2017 18:24:50 +0000 |
treeherder | mozilla-inbound@51bf67737ecb [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | pbro |
bugs | 1302197 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
devtools/server/actors/highlighters.css | file | annotate | diff | comparison | revisions | |
devtools/server/actors/highlighters/css-grid.js | file | annotate | diff | comparison | revisions |
--- a/devtools/server/actors/highlighters.css +++ b/devtools/server/actors/highlighters.css @@ -225,23 +225,25 @@ left: 0; image-rendering: -moz-crisp-edges; } :-moz-native-anonymous .css-grid-regions { opacity: 0.6; } -:-moz-native-anonymous .css-grid-areas { +:-moz-native-anonymous .css-grid-areas, +:-moz-native-anonymous .css-grid-cells { fill: #CEC0ED; stroke: none; } -:-moz-native-anonymous .css-grid-infobar-areaname { - color: hsl(285,100%, 75%); +:-moz-native-anonymous .css-grid-area-infobar-name, +:-moz-native-anonymous .css-grid-cell-infobar-position { + color: hsl(285, 100%, 75%); } /* CSS Transform Highlighter */ :-moz-native-anonymous .css-transform-transformed { fill: var(--highlighter-content-color); opacity: 0.8; }
--- a/devtools/server/actors/highlighters/css-grid.js +++ b/devtools/server/actors/highlighters/css-grid.js @@ -16,19 +16,21 @@ const { const { getCurrentZoom, setIgnoreLayoutChanges, getWindowDimensions } = require("devtools/shared/layout/utils"); const { stringifyGridFragments } = require("devtools/server/actors/utils/css-grid-utils"); const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled"; + const DEFAULT_GRID_COLOR = "#4B0082"; + +const COLUMNS = "cols"; const ROWS = "rows"; -const COLUMNS = "cols"; const GRID_LINES_PROPERTIES = { "edge": { lineDash: [0, 0], alpha: 1, }, "explicit": { lineDash: [5, 3], @@ -64,41 +66,56 @@ const COLUMN_KEY = {}; * h.show(node, options); * h.hide(); * h.destroy(); * * Available Options: * - color(colorValue) * @param {String} colorValue * The color that should be used to draw the highlighter for this grid. + * - showAllGridAreas(isShown) + * @param {Boolean} isShown + * Shows all the grid area highlights for the current grid if isShown is true. * - showGridArea(areaName) * @param {String} areaName * Shows the grid area highlight for the given area name. - * - showAllGridAreas - * Shows all the grid area highlights for the current grid. + * - showGridCell({ gridFragmentIndex: Number, rowNumber: Number, columnNumber: Number }) + * @param {Object} { gridFragmentIndex: Number, rowNumber: Number, + * columnNumber: Number } + * An object containing the grid fragment index, row and column numbers to the + * corresponding grid cell to highlight for the current grid. * - showGridLineNumbers(isShown) - * @param {Boolean} + * @param {Boolean} isShown * Displays the grid line numbers on the grid lines if isShown is true. * - showInfiniteLines(isShown) * @param {Boolean} isShown * Displays an infinite line to represent the grid lines if isShown is true. * * Structure: * <div class="highlighter-container"> * <canvas id="css-grid-canvas" class="css-grid-canvas"> * <svg class="css-grid-elements" hidden="true"> * <g class="css-grid-regions"> * <path class="css-grid-areas" points="..." /> + * <path class="css-grid-cells" points="..." /> * </g> * </svg> - * <div class="css-grid-infobar-container"> + * <div class="css-grid-area-infobar-container"> * <div class="css-grid-infobar"> * <div class="css-grid-infobar-text"> - * <span class="css-grid-infobar-areaname">Grid Area Name</span> - * <span class="css-grid-infobar-dimensions"Grid Area Dimensions></span> + * <span class="css-grid-area-infobar-name">Grid Area Name</span> + * <span class="css-grid-area-infobar-dimensions"Grid Area Dimensions></span> + * </div> + * </div> + * </div> + * <div class="css-grid-cell-infobar-container"> + * <div class="css-grid-infobar"> + * <div class="css-grid-infobar-text"> + * <span class="css-grid-cell-infobar-position">Grid Cell Position</span> + * <span class="css-grid-cell-infobar-dimensions"Grid Cell Dimensions></span> * </div> * </div> * </div> * </div> */ function CssGridHighlighter(highlighterEnv) { AutoRefreshHighlighter.call(this, highlighterEnv); @@ -178,58 +195,114 @@ CssGridHighlighter.prototype = extend(Au parent: regions, attributes: { "class": "areas", "id": "areas" }, prefix: this.ID_CLASS_PREFIX }); - // Building the grid infobar markup - let infobarContainer = createNode(this.win, { + createSVGNode(this.win, { + nodeType: "path", + parent: regions, + attributes: { + "class": "cells", + "id": "cells" + }, + prefix: this.ID_CLASS_PREFIX + }); + + // Building the grid area infobar markup + let areaInfobarContainer = createNode(this.win, { parent: container, attributes: { - "class": "infobar-container", - "id": "infobar-container", + "class": "area-infobar-container", + "id": "area-infobar-container", "position": "top", "hidden": "true" }, prefix: this.ID_CLASS_PREFIX }); - let infobar = createNode(this.win, { - parent: infobarContainer, + let areaInfobar = createNode(this.win, { + parent: areaInfobarContainer, attributes: { "class": "infobar" }, prefix: this.ID_CLASS_PREFIX }); - let textbox = createNode(this.win, { - parent: infobar, + let areaTextbox = createNode(this.win, { + parent: areaInfobar, attributes: { "class": "infobar-text" }, prefix: this.ID_CLASS_PREFIX }); createNode(this.win, { nodeType: "span", - parent: textbox, + parent: areaTextbox, attributes: { - "class": "infobar-areaname", - "id": "infobar-areaname" + "class": "area-infobar-name", + "id": "area-infobar-name" }, prefix: this.ID_CLASS_PREFIX }); createNode(this.win, { nodeType: "span", - parent: textbox, + parent: areaTextbox, + attributes: { + "class": "area-infobar-dimensions", + "id": "area-infobar-dimensions" + }, + prefix: this.ID_CLASS_PREFIX + }); + + // Building the grid cell infobar markup + let cellInfobarContainer = createNode(this.win, { + parent: container, + attributes: { + "class": "cell-infobar-container", + "id": "cell-infobar-container", + "position": "top", + "hidden": "true" + }, + prefix: this.ID_CLASS_PREFIX + }); + + let cellInfobar = createNode(this.win, { + parent: cellInfobarContainer, attributes: { - "class": "infobar-dimensions", - "id": "infobar-dimensions" + "class": "infobar" + }, + prefix: this.ID_CLASS_PREFIX + }); + + let cellTextbox = createNode(this.win, { + parent: cellInfobar, + attributes: { + "class": "infobar-text" + }, + prefix: this.ID_CLASS_PREFIX + }); + createNode(this.win, { + nodeType: "span", + parent: cellTextbox, + attributes: { + "class": "cell-infobar-position", + "id": "cell-infobar-position" + }, + prefix: this.ID_CLASS_PREFIX + }); + createNode(this.win, { + nodeType: "span", + parent: cellTextbox, + attributes: { + "class": "cell-infobar-dimensions", + "id": "cell-infobar-dimensions" }, prefix: this.ID_CLASS_PREFIX }); return container; }, destroy() { @@ -342,33 +415,53 @@ CssGridHighlighter.prototype = extend(Au /** * Shows the grid area highlight for the given area name. * * @param {String} areaName * Grid area name. */ showGridArea(areaName) { this.renderGridArea(areaName); - this._showGridArea(); }, /** * Shows all the grid area highlights for the current grid. */ showAllGridAreas() { this.renderGridArea(); - this._showGridArea(); }, /** * Clear the grid area highlights. */ clearGridAreas() { - let box = this.getElement("areas"); - box.setAttribute("d", ""); + let areas = this.getElement("areas"); + areas.setAttribute("d", ""); + }, + + /** + * Shows the grid cell highlight for the given grid cell options. + * + * @param {Number} options.gridFragmentIndex + * Index of the grid fragment to render the grid cell highlight. + * @param {Number} options.rowNumber + * Row number of the grid cell to highlight. + * @param {Number} options.columnNumber + * Column number of the grid cell to highlight. + */ + showGridCell({ gridFragmentIndex, rowNumber, columnNumber }) { + this.renderGridCell(gridFragmentIndex, rowNumber, columnNumber); + }, + + /** + * Clear the grid cell highlights. + */ + clearGridCell() { + let cells = this.getElement("cells"); + cells.setAttribute("d", ""); }, /** * Checks if the current node has a CSS Grid layout. * * @return {Boolean} true if the current node has a CSS grid layout, false otherwise. */ isGrid() { @@ -420,76 +513,97 @@ CssGridHighlighter.prototype = extend(Au // Display the grid area highlights if needed. if (this.options.showAllGridAreas) { this.showAllGridAreas(); } else if (this.options.showGridArea) { this.showGridArea(this.options.showGridArea); } + // Display the grid cell highlights if needed. + if (this.options.showGridCell) { + this.showGridCell(this.options.showGridCell); + } + this._showGrid(); + this._showGridElements(); root.setAttribute("style", `position:absolute; width:${width}px;height:${height}px; overflow:hidden`); setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement); return true; }, /** - * Update the grid information displayed in the grid info bar. + * Update the grid information displayed in the grid area info bar. * * @param {GridArea} area * The grid area object. * @param {Number} x1 * The first x-coordinate of the grid area rectangle. * @param {Number} x2 * The second x-coordinate of the grid area rectangle. * @param {Number} y1 * The first y-coordinate of the grid area rectangle. * @param {Number} y2 * The second y-coordinate of the grid area rectangle. */ - _updateInfobar(area, x1, x2, y1, y2) { + _updateGridAreaInfobar(area, x1, x2, y1, y2) { let width = x2 - x1; let height = y2 - y1; let dim = parseFloat(width.toPrecision(6)) + " \u00D7 " + parseFloat(height.toPrecision(6)); - this.getElement("infobar-areaname").setTextContent(area.name); - this.getElement("infobar-dimensions").setTextContent(dim); + this.getElement("area-infobar-name").setTextContent(area.name); + this.getElement("area-infobar-dimensions").setTextContent(dim); + + let container = this.getElement("area-infobar-container"); + this._moveInfobar(container, x1, x2, y1, y2); + }, - this._moveInfobar(x1, x2, y1, y2); + _updateGridCellInfobar(rowNumber, columnNumber, x1, x2, y1, y2) { + let width = x2 - x1; + let height = y2 - y1; + let dim = parseFloat(width.toPrecision(6)) + + " \u00D7 " + + parseFloat(height.toPrecision(6)); + let position = `${rowNumber}\/${columnNumber}`; + + this.getElement("cell-infobar-position").setTextContent(position); + this.getElement("cell-infobar-dimensions").setTextContent(dim); + + let container = this.getElement("cell-infobar-container"); + this._moveInfobar(container, x1, x2, y1, y2); }, /** - * Move the grid infobar to the right place in the highlighter. + * Move the given grid infobar to the right place in the highlighter. * * @param {Number} x1 - * The first x-coordinate of the grid area rectangle. + * The first x-coordinate of the grid rectangle. * @param {Number} x2 - * The second x-coordinate of the grid area rectangle. + * The second x-coordinate of the grid rectangle. * @param {Number} y1 - * The first y-coordinate of the grid area rectangle. + * The first y-coordinate of the grid rectangle. * @param {Number} y2 - * The second y-coordinate of the grid area rectangle. + * The second y-coordinate of the grid rectangle. */ - _moveInfobar(x1, x2, y1, y2) { + _moveInfobar(container, x1, x2, y1, y2) { let bounds = { bottom: y2, height: y2 - y1, left: x1, right: x2, top: y1, width: x2 - x1, x: x1, y: y1, }; - let container = this.getElement("infobar-container"); moveInfobar(container, bounds, this.win); }, clearCanvas(width, height) { let ratio = parseFloat((this.win.devicePixelRatio || 1).toFixed(2)); // Resize the canvas taking the dpr into account so as to have crisp lines. @@ -613,17 +727,17 @@ CssGridHighlighter.prototype = extend(Au * 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 + * @param {String} 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); @@ -737,56 +851,108 @@ CssGridHighlighter.prototype = extend(Au let path = "M" + x1 + "," + y1 + " " + "L" + x2 + "," + y1 + " " + "L" + x2 + "," + y2 + " " + "L" + x1 + "," + y2; paths.push(path); // Update and show the info bar when only displaying a single grid area. if (areaName) { - this._updateInfobar(area, x1, x2, y1, y2); - this._showInfoBar(); + this._updateGridAreaInfobar(area, x1, x2, y1, y2); + this._showGridAreaInfoBar(); } } } - let box = this.getElement("areas"); - box.setAttribute("d", paths.join(" ")); + let areas = this.getElement("areas"); + areas.setAttribute("d", paths.join(" ")); }, /** - * Hide the highlighter, the canvas and the infobar. + * Render the grid cell highlight for the given grid fragment index, row and column + * number. + * + * @param {Number} gridFragmentIndex + * Index of the grid fragment to render the grid cell highlight. + * @param {Number} rowNumber + * Row number of the grid cell to highlight. + * @param {Number} columnNumber + * Column number of the grid cell to highlight. + */ + renderGridCell(gridFragmentIndex, rowNumber, columnNumber) { + let fragment = this.gridData[gridFragmentIndex]; + if (!fragment) { + return; + } + + let row = fragment.rows.tracks[rowNumber - 1]; + let column = fragment.cols.tracks[columnNumber - 1]; + + if (!row || !column) { + return; + } + + let currentZoom = getCurrentZoom(this.win); + let {bounds} = this.currentQuads.content[gridFragmentIndex]; + + let x1 = column.start + (bounds.left / currentZoom); + let x2 = column.start + column.breadth + (bounds.left / currentZoom); + let y1 = row.start + (bounds.top / currentZoom); + let y2 = row.start + row.breadth + (bounds.top / currentZoom); + + let path = "M" + x1 + "," + y1 + " " + + "L" + x2 + "," + y1 + " " + + "L" + x2 + "," + y2 + " " + + "L" + x1 + "," + y2; + let cells = this.getElement("cells"); + cells.setAttribute("d", path); + + this._updateGridCellInfobar(rowNumber, columnNumber, x1, x2, y1, y2); + this._showGridCellInfoBar(); + }, + + /** + * Hide the highlighter, the canvas and the infobars. */ _hide() { setIgnoreLayoutChanges(true); this._hideGrid(); - this._hideGridArea(); - this._hideInfoBar(); + this._hideGridElements(); + this._hideGridAreaInfoBar(); + this._hideGridCellInfoBar(); setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement); }, _hideGrid() { this.getElement("canvas").setAttribute("hidden", "true"); }, _showGrid() { this.getElement("canvas").removeAttribute("hidden"); }, - _hideGridArea() { + _hideGridElements() { this.getElement("elements").setAttribute("hidden", "true"); }, - _showGridArea() { + _showGridElements() { this.getElement("elements").removeAttribute("hidden"); }, - _hideInfoBar() { - this.getElement("infobar-container").setAttribute("hidden", "true"); + _hideGridAreaInfoBar() { + this.getElement("area-infobar-container").setAttribute("hidden", "true"); }, - _showInfoBar() { - this.getElement("infobar-container").removeAttribute("hidden"); + _showGridAreaInfoBar() { + this.getElement("area-infobar-container").removeAttribute("hidden"); + }, + + _hideGridCellInfoBar() { + this.getElement("cell-infobar-container").setAttribute("hidden", "true"); + }, + + _showGridCellInfoBar() { + this.getElement("cell-infobar-container").removeAttribute("hidden"); }, }); exports.CssGridHighlighter = CssGridHighlighter;