Bug 1297100 - Display CSS Grid layouts when highlighting elements in the page r=pbro
MozReview-Commit-ID: 3i9XkYjWivo
--- a/devtools/server/actors/highlighters.css
+++ b/devtools/server/actors/highlighters.css
@@ -59,16 +59,22 @@
}
:-moz-native-anonymous .highlighter-container.box-model {
/* Make the box-model container have a z-index other than auto so it always sits above
other highlighters. */
z-index: 1;
}
+:-moz-native-anonymous .highlighter-container.css-grid {
+ /* Make the css grid container have a z-index greater than the box-model so it always
+ sits above other highlighters. */
+ z-index: 2;
+}
+
:-moz-native-anonymous .highlighter-container [hidden] {
display: none;
}
:-moz-native-anonymous .highlighter-container [dragging] {
cursor: grabbing;
}
--- a/devtools/server/actors/highlighters/box-model.js
+++ b/devtools/server/actors/highlighters/box-model.js
@@ -16,16 +16,18 @@ const {
} = require("./utils/markup");
const {
setIgnoreLayoutChanges,
getCurrentZoom,
} = require("devtools/shared/layout/utils");
const { getNodeDisplayName } = require("devtools/server/actors/inspector/utils");
const nodeConstants = require("devtools/shared/dom-node-constants");
+loader.lazyRequireGetter(this, "CssGridHighlighter", "devtools/server/actors/highlighters/css-grid", true);
+
// Note that the order of items in this array is important because it is used
// for drawing the BoxModelHighlighter's path elements correctly.
const BOX_MODEL_REGIONS = ["margin", "border", "padding", "content"];
const BOX_MODEL_SIDES = ["top", "right", "bottom", "left"];
// Width of boxmodelhighlighter guides
const GUIDE_STROKE_WIDTH = 1;
// FIXME: add ":visited" and ":link" after bug 713106 is fixed
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
@@ -269,19 +271,33 @@ class BoxModelHighlighter extends AutoRe
this.highlighterEnv.off("will-navigate", this.onWillNavigate);
const { pageListenerTarget } = this.highlighterEnv;
if (pageListenerTarget) {
pageListenerTarget.removeEventListener("pagehide", this.onPageHide);
}
this.markup.destroy();
+
+ if (this._cssGridHighlighter) {
+ this._cssGridHighlighter.destroy();
+ this._cssGridHighlighter = null;
+ }
+
AutoRefreshHighlighter.prototype.destroy.call(this);
}
+ get cssGridHighlighter() {
+ if (!this._cssGridHighlighter) {
+ this._cssGridHighlighter = new CssGridHighlighter(this.highlighterEnv);
+ }
+
+ return this._cssGridHighlighter;
+ }
+
getElement(id) {
return this.markup.getElement(this.ID_CLASS_PREFIX + id);
}
/**
* Override the AutoRefreshHighlighter's _isNodeValid method to also return true for
* text nodes since these can also be highlighted.
* @param {DOMNode} node
@@ -345,39 +361,74 @@ class BoxModelHighlighter extends AutoRe
}
this._showBoxModel();
shown = true;
} else {
// Nothing to highlight (0px rectangle like a <script> tag for instance)
this._hide();
}
+ this._updateGridHighlighter();
+
setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement);
return shown;
}
+ /**
+ * Update the grid highlighter on the current highlighted node. Show the CSS grid
+ * highlighter if the current node is a grid container or grid item.
+ */
+ _updateGridHighlighter() {
+ this._hideCssGridHighlighter();
+
+ let gridNode;
+ if (this.currentNode &&
+ this.currentNode.getGridFragments &&
+ this.currentNode.getGridFragments().length) {
+ gridNode = this.currentNode;
+ } else if (this.currentNode.parentNode &&
+ this.currentNode.parentNode.getGridFragments &&
+ this.currentNode.parentNode.getGridFragments().length) {
+ gridNode = this.currentNode.parentNode;
+ }
+
+ if (gridNode) {
+ this.cssGridHighlighter.show(gridNode, { showBoldGridBorders: true });
+ }
+ }
+
_scrollUpdate() {
this._moveInfobar();
}
/**
* Hide the highlighter, the outline and the infobar.
*/
_hide() {
setIgnoreLayoutChanges(true);
this._untrackMutations();
this._hideBoxModel();
this._hideInfobar();
+ this._hideCssGridHighlighter();
setIgnoreLayoutChanges(false, this.highlighterEnv.window.document.documentElement);
}
/**
+ * Hide the CSS Grid highlighter.
+ */
+ _hideCssGridHighlighter() {
+ if (this._cssGridHighlighter) {
+ this.cssGridHighlighter.hide();
+ }
+ }
+
+ /**
* Hide the infobar
*/
_hideInfobar() {
this.getElement("infobar-container").setAttribute("hidden", "true");
}
/**
* Show the infobar
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -136,16 +136,20 @@ const gCachedGridPattern = new Map();
*
* 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.
+ * - showBoldGridBorders(isShown)
+ * Shows a bold grid border for the first and last lines of the grid. This option
+ * is used in the box-model highlighter to show a bold grid border when overlapping
+ * with the box-model highlight.
* - showGridArea(areaName)
* @param {String} areaName
* Shows the grid area highlight for the given area name.
* - showGridAreasOverlay(isShown)
* @param {Boolean} isShown
* Displays an overlay of all the grid areas for the current grid container if
* isShown is true.
* - showGridCell({ gridFragmentIndex: Number, rowNumber: Number, columnNumber: Number })
@@ -226,17 +230,17 @@ class CssGridHighlighter extends AutoRef
// on a page that has scrolled already.
updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
this._winDimensions);
}
_buildMarkup() {
const container = createNode(this.win, {
attributes: {
- "class": "highlighter-container"
+ "class": "highlighter-container css-grid"
}
});
const root = createNode(this.win, {
parent: container,
attributes: {
"id": "root",
"class": "root"
@@ -1407,18 +1411,20 @@ class CssGridHighlighter extends AutoRef
* @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 {String} lineType
* The grid line type - "edge", "explicit", or "implicit".
+ * @param {Boolean} isFirstOrLastLine
+ * Whether or not this is the first or last line for a row or column grid line.
*/
- renderLine(linePos, startPos, endPos, dimensionType, lineType) {
+ renderLine(linePos, startPos, endPos, dimensionType, lineType, isFirstOrLastLine) {
const { devicePixelRatio } = this.win;
const lineWidth = getDisplayPixelRatio(this.win);
const offset = (lineWidth / 2) % 1;
const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
linePos = Math.round(linePos);
startPos = Math.round(startPos);
@@ -1442,19 +1448,20 @@ class CssGridHighlighter extends AutoRef
} else {
drawLine(this.ctx, startPos, linePos, endPos, linePos, lineOptions);
}
this.ctx.strokeStyle = this.color;
this.ctx.globalAlpha = GRID_LINES_PROPERTIES[lineType].alpha;
if (GRID_LINES_PROPERTIES[lineType].lineWidth) {
- this.ctx.lineWidth = GRID_LINES_PROPERTIES[lineType].lineWidth * devicePixelRatio;
+ this.ctx.lineWidth = GRID_LINES_PROPERTIES[lineType].lineWidth * devicePixelRatio *
+ (isFirstOrLastLine ? 2 : 1);
} else {
- this.ctx.lineWidth = lineWidth;
+ this.ctx.lineWidth = lineWidth * (isFirstOrLastLine ? 2 : 1);
}
this.ctx.stroke();
this.ctx.restore();
}
/**
* Render the grid lines given the grid dimension information of the
@@ -1471,25 +1478,30 @@ class CssGridHighlighter extends AutoRef
* of the grid dimension.
* @param {Number} endPos
* The end position of the cross side ("left" for ROWS and "top" for COLUMNS)
* of the grid dimension.
*/
renderLines(gridDimension, dimensionType, startPos, endPos) {
const { lines, tracks } = gridDimension;
const lastEdgeLineIndex = this.getLastEdgeLineIndex(tracks);
+ const showBoldGridBorders = this.options.showBoldGridBorders;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const linePos = line.start;
if (i == 0 || i == lastEdgeLineIndex) {
- this.renderLine(linePos, startPos, endPos, dimensionType, "edge");
+ const isFirstOrLastLine = showBoldGridBorders &&
+ (i == 0 || i == lines.length - 1);
+ this.renderLine(linePos, startPos, endPos, dimensionType, "edge",
+ isFirstOrLastLine);
} else {
- this.renderLine(linePos, startPos, endPos, dimensionType, tracks[i - 1].type);
+ this.renderLine(linePos, startPos, endPos, dimensionType, tracks[i - 1].type,
+ showBoldGridBorders && i == lines.length - 1);
}
// Render a second line to illustrate the gutter for non-zero breadth.
if (line.breadth > 0) {
this.renderGridGap(linePos, startPos, endPos, line.breadth, dimensionType);
this.renderLine(linePos + line.breadth, startPos, endPos, dimensionType,
tracks[i].type);
}