Bug 940275 - Part 1: Add positioning properties to box model r=gl
authorStanford Lockhart <lockhart@cs.dal.ca>
Tue, 28 Feb 2017 18:18:28 -0400
changeset 347738 9ed72c2f16d8
parent 347737 323c768fdc43
child 347739 fd8e7d9053dc
push id88080
push usergabriel.luong@gmail.com
push dateWed, 15 Mar 2017 13:43:24 +0000
treeherdermozilla-inbound@9ed72c2f16d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs940275
milestone55.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
Bug 940275 - Part 1: Add positioning properties to box model r=gl MozReview-Commit-ID: AB5fREjDhsD
devtools/client/inspector/boxmodel/box-model.js
devtools/client/inspector/boxmodel/components/BoxModelMain.js
devtools/client/locales/en-US/boxmodel.properties
devtools/client/themes/boxmodel.css
devtools/client/themes/layout.css
devtools/server/actors/styles.js
--- a/devtools/client/inspector/boxmodel/box-model.js
+++ b/devtools/client/inspector/boxmodel/box-model.js
@@ -293,16 +293,20 @@ BoxModel.prototype = {
         if (property.substring(0, 7) == "border-") {
           let bprop = property.substring(0, property.length - 5) + "style";
           let style = session.getProperty(bprop);
           if (!style || style == "none" || style == "hidden") {
             properties.push({ name: bprop, value: "solid" });
           }
         }
 
+        if (property.substring(0, 9) == "position-") {
+          properties[0].name = property.substring(9);
+        }
+
         session.setProperties(properties).catch(e => console.error(e));
       },
       done: (value, commit) => {
         editor.elt.parentNode.classList.remove("boxmodel-editing");
         if (!commit) {
           session.revert().then(() => {
             session.destroy();
           }, e => console.error(e));
--- a/devtools/client/inspector/boxmodel/components/BoxModelMain.js
+++ b/devtools/client/inspector/boxmodel/components/BoxModelMain.js
@@ -78,108 +78,179 @@ module.exports = createClass({
       value = "auto";
     } else if (layout[property]) {
       value = parseFloat(layout[property]);
     }
 
     return value;
   },
 
+  getPositionValue(property) {
+    let { layout } = this.props.boxModel;
+
+    if (layout.position === "static") {
+      return "-";
+    }
+    return layout[property] ? parseFloat(layout[property]) : "-";
+  },
+
   onHighlightMouseOver(event) {
     let region = event.target.getAttribute("data-box");
     if (!region) {
       this.props.onHideBoxModelHighlighter();
     }
 
     this.props.onShowBoxModelHighlighter({
       region,
       showOnly: region,
       onlyRegionArea: true,
     });
   },
 
   render() {
     let { boxModel, onShowBoxModelEditor } = this.props;
     let { layout } = boxModel;
-    let { height, width } = layout;
+    let { height, width, position } = layout;
 
     let borderTop = this.getBorderOrPaddingValue("border-top-width");
     let borderRight = this.getBorderOrPaddingValue("border-right-width");
     let borderBottom = this.getBorderOrPaddingValue("border-bottom-width");
     let borderLeft = this.getBorderOrPaddingValue("border-left-width");
 
     let paddingTop = this.getBorderOrPaddingValue("padding-top");
     let paddingRight = this.getBorderOrPaddingValue("padding-right");
     let paddingBottom = this.getBorderOrPaddingValue("padding-bottom");
     let paddingLeft = this.getBorderOrPaddingValue("padding-left");
 
+    let displayPosition = layout.position && layout.position != "static";
+    let positionTop = this.getPositionValue("top");
+    let positionRight = this.getPositionValue("right");
+    let positionBottom = this.getPositionValue("bottom");
+    let positionLeft = this.getPositionValue("left");
+
     let marginTop = this.getMarginValue("margin-top", "top");
     let marginRight = this.getMarginValue("margin-right", "right");
     let marginBottom = this.getMarginValue("margin-bottom", "bottom");
     let marginLeft = this.getMarginValue("margin-left", "left");
 
     height = this.getHeightValue(height);
     width = this.getWidthValue(width);
 
     return dom.div(
       {
         className: "boxmodel-main",
         onMouseOver: this.onHighlightMouseOver,
         onMouseOut: this.props.onHideBoxModelHighlighter,
       },
-      dom.span(
-        {
-          className: "boxmodel-legend",
-          "data-box": "margin",
-          title: BOXMODEL_L10N.getStr("boxmodel.margin"),
-        },
-        BOXMODEL_L10N.getStr("boxmodel.margin")
-      ),
+      displayPosition ?
+        dom.span(
+          {
+            className: "boxmodel-legend",
+            "data-box": "position",
+            title: BOXMODEL_L10N.getFormatStr("boxmodel.position", position),
+          },
+          BOXMODEL_L10N.getFormatStr("boxmodel.position", position)
+        )
+        :
+        null,
       dom.div(
         {
-          className: "boxmodel-margins",
-          "data-box": "margin",
-          title: BOXMODEL_L10N.getStr("boxmodel.margin"),
+          className: "boxmodel-box"
         },
         dom.span(
           {
             className: "boxmodel-legend",
-            "data-box": "border",
-            title: BOXMODEL_L10N.getStr("boxmodel.border"),
+            "data-box": "margin",
+            title: BOXMODEL_L10N.getStr("boxmodel.margin"),
           },
-          BOXMODEL_L10N.getStr("boxmodel.border")
+          BOXMODEL_L10N.getStr("boxmodel.margin")
         ),
         dom.div(
           {
-            className: "boxmodel-borders",
-            "data-box": "border",
-            title: BOXMODEL_L10N.getStr("boxmodel.border"),
+            className: "boxmodel-margins",
+            "data-box": "margin",
+            title: BOXMODEL_L10N.getStr("boxmodel.margin"),
           },
           dom.span(
             {
               className: "boxmodel-legend",
-              "data-box": "padding",
-              title: BOXMODEL_L10N.getStr("boxmodel.padding"),
+              "data-box": "border",
+              title: BOXMODEL_L10N.getStr("boxmodel.border"),
             },
-            BOXMODEL_L10N.getStr("boxmodel.padding")
+            BOXMODEL_L10N.getStr("boxmodel.border")
           ),
           dom.div(
             {
-              className: "boxmodel-paddings",
-              "data-box": "padding",
-              title: BOXMODEL_L10N.getStr("boxmodel.padding"),
+              className: "boxmodel-borders",
+              "data-box": "border",
+              title: BOXMODEL_L10N.getStr("boxmodel.border"),
             },
-            dom.div({
-              className: "boxmodel-content",
-              "data-box": "content",
-              title: BOXMODEL_L10N.getStr("boxmodel.content"),
-            })
+            dom.span(
+              {
+                className: "boxmodel-legend",
+                "data-box": "padding",
+                title: BOXMODEL_L10N.getStr("boxmodel.padding"),
+              },
+              BOXMODEL_L10N.getStr("boxmodel.padding")
+            ),
+            dom.div(
+              {
+                className: "boxmodel-paddings",
+                "data-box": "padding",
+                title: BOXMODEL_L10N.getStr("boxmodel.padding"),
+              },
+              dom.div({
+                className: "boxmodel-content",
+                "data-box": "content",
+                title: BOXMODEL_L10N.getStr("boxmodel.content"),
+              })
+            )
           )
         )
       ),
+      displayPosition ?
+        BoxModelEditable({
+          box: "position",
+          direction: "top",
+          property: "position-top",
+          textContent: positionTop,
+          onShowBoxModelEditor,
+        })
+        :
+        null,
+      displayPosition ?
+        BoxModelEditable({
+          box: "position",
+          direction: "right",
+          property: "position-right",
+          textContent: positionRight,
+          onShowBoxModelEditor,
+        })
+        :
+        null,
+      displayPosition ?
+        BoxModelEditable({
+          box: "position",
+          direction: "bottom",
+          property: "position-bottom",
+          textContent: positionBottom,
+          onShowBoxModelEditor,
+        })
+        :
+        null,
+      displayPosition ?
+        BoxModelEditable({
+          box: "position",
+          direction: "left",
+          property: "position-left",
+          textContent: positionLeft,
+          onShowBoxModelEditor,
+        })
+        :
+        null,
       BoxModelEditable({
         box: "margin",
         direction: "top",
         property: "margin-top",
         textContent: marginTop,
         onShowBoxModelEditor,
       }),
       BoxModelEditable({
--- a/devtools/client/locales/en-US/boxmodel.properties
+++ b/devtools/client/locales/en-US/boxmodel.properties
@@ -10,16 +10,20 @@
 # You want to make that choice consistent across the developer tools.
 # A good criteria is the language in which you'd find the best
 # documentation on web development on the web.
 
 # LOCALIZATION NOTE (boxmodel.title) This is the title of the box model panel and is
 # displayed as a label.
 boxmodel.title=Box Model
 
+# LOCALIZATION NOTE (boxmodel.position) This refers to the position in the box model and
+# might be displayed as a label or as a tooltip.
+boxmodel.position=position: %S
+
 # LOCALIZATION NOTE (boxmodel.margin) This refers to the margin in the box model and
 # might be displayed as a label or as a tooltip.
 boxmodel.margin=margin
 
 # LOCALIZATION NOTE (boxmodel.border) This refers to the border in the box model and
 # might be displayed as a label or as a tooltip.
 boxmodel.border=border
 
--- a/devtools/client/themes/boxmodel.css
+++ b/devtools/client/themes/boxmodel.css
@@ -6,16 +6,17 @@
  * This is the stylesheet of the Box Model view implemented in the layout panel.
  */
 
 .boxmodel-container {
   /* The view will grow bigger as the window gets resized, until 400px */
   max-width: 400px;
   margin: 0px auto;
   padding: 0;
+  overflow: auto;
 }
 
 /* Header */
 
 .boxmodel-header,
 .boxmodel-info {
   display: flex;
   align-items: center;
@@ -25,24 +26,28 @@
 .layout-geometry-editor::before {
   background: url(images/geometry-editor.svg) no-repeat center center / 16px 16px;
 }
 
 /* Main: contains the box-model regions */
 
 .boxmodel-main {
   position: relative;
-  box-sizing: border-box;
-  /* The regions are semi-transparent, so the white background is partly
-     visible */
-  background-color: white;
   color: var(--theme-selection-color);
   /* Make sure there is some space between the window's edges and the regions */
   margin: 14px 14px 4px 14px;
   width: calc(100% - 2 * 14px);
+  min-width: 240px;
+}
+
+.boxmodel-box {
+  margin: 25px;
+  /* The regions are semi-transparent, so the white background is partly
+     visible */
+  background-color: white;
 }
 
 .boxmodel-margin,
 .boxmodel-size {
   color: var(--theme-highlight-blue);
 }
 
 /* Regions are 3 nested elements with wide borders and outlines */
@@ -79,22 +84,16 @@
   border-color: #6a5acd;
 }
 
 .boxmodel-content {
   background-color: #87ceeb;
 }
 
 .theme-firebug .boxmodel-main,
-.theme-firebug .boxmodel-borders,
-.theme-firebug .boxmodel-content {
-  border-style: solid;
-}
-
-.theme-firebug .boxmodel-main,
 .theme-firebug .boxmodel-header {
   font-family: var(--proportional-font-family);
 }
 
 .theme-firebug .boxmodel-main {
   color: var(--theme-body-color);
   font-size: var(--theme-toolbar-font-size);
 }
@@ -146,83 +145,145 @@
   top: 1px;
 }
 
 .boxmodel-margin.boxmodel-bottom {
   bottom: 2px;
 }
 
 .boxmodel-size,
+.boxmodel-position.boxmodel-left,
+.boxmodel-position.boxmodel-right,
 .boxmodel-margin.boxmodel-left,
 .boxmodel-margin.boxmodel-right,
 .boxmodel-border.boxmodel-left,
 .boxmodel-border.boxmodel-right,
 .boxmodel-padding.boxmodel-left,
 .boxmodel-padding.boxmodel-right {
   top: 22px;
   line-height: 80px;
 }
 
 .boxmodel-size {
   width: calc(100% - 2px);
 }
 
+.boxmodel-position.boxmodel-top,
+.boxmodel-position.boxmodel-bottom,
+.boxmodel-position.boxmodel-left,
+.boxmodel-position.boxmodel-right,
 .boxmodel-margin.boxmodel-right,
 .boxmodel-margin.boxmodel-left,
 .boxmodel-border.boxmodel-left,
 .boxmodel-border.boxmodel-right,
 .boxmodel-padding.boxmodel-right,
 .boxmodel-padding.boxmodel-left {
   width: 21px;
 }
 
 .boxmodel-padding.boxmodel-left {
-  left: 35px;
+  left: 60px;
 }
 
 .boxmodel-padding.boxmodel-right {
-  right: 35px;
+  right: 60px;
 }
 
 .boxmodel-border.boxmodel-left {
-  left: 16px;
+  left: 41px;
 }
 
 .boxmodel-border.boxmodel-right {
-  right: 17px;
+  right: 42px;
 }
 
 .boxmodel-margin.boxmodel-right {
-  right: 0;
+  right: 25px;
 }
 
 .boxmodel-margin.boxmodel-left {
-  left: 0;
+  left: 25px;
 }
 
 .boxmodel-rotate.boxmodel-left:not(.boxmodel-editing) {
   transform: rotate(-90deg);
 }
 
 .boxmodel-rotate.boxmodel-right:not(.boxmodel-editing) {
   transform: rotate(90deg);
 }
 
+.boxmodel-rotate.boxmodel-left.boxmodel-position:not(.boxmodel-editing) {
+  border-top: none;
+  border-right: 1px solid var(--theme-highlight-purple);
+  width: auto;
+  height: 30px;
+}
+
+.boxmodel-rotate.boxmodel-right.boxmodel-position:not(.boxmodel-editing) {
+  border-top: none;
+  border-left: 1px solid var(--theme-highlight-purple);
+  width: auto;
+  height: 30px;
+}
+
+/* Box Model Positioning: contains top, right, bottom, left */
+
+.boxmodel-position {
+  color: var(--theme-highlight-purple);
+}
+
+.boxmodel-position.boxmodel-top,
+.boxmodel-position.boxmodel-bottom {
+  border-left: 1px solid var(--theme-highlight-purple);
+  left: 49.5%;
+  padding-left: 1px;
+}
+
+.boxmodel-position.boxmodel-right,
+.boxmodel-position.boxmodel-left {
+  border-top: 1px solid var(--theme-highlight-purple);
+  line-height: 15px;
+  top: 49.5%;
+  width: 30px;
+}
+
+.boxmodel-position.boxmodel-top {
+  top: -18px;
+}
+
+.boxmodel-position.boxmodel-right {
+  right: -9px;
+}
+
+.boxmodel-position.boxmodel-bottom {
+  bottom: -18px;
+}
+
+.boxmodel-position.boxmodel-left {
+  left: -9px;
+}
+
 /* Legend: displayed inside regions */
 
 .boxmodel-legend {
   position: absolute;
   margin: 2px 6px;
   z-index: 1;
 }
 
 .boxmodel-legend[data-box="margin"] {
   color: var(--theme-highlight-blue);
 }
 
+.boxmodel-legend[data-box="position"] {
+  color: var(--theme-highlight-purple);
+  margin: -18px -9px;
+}
+
 /* Editable fields */
 
 .boxmodel-editable {
   border: 1px dashed transparent;
   -moz-user-select: none;
 }
 
 .boxmodel-editable:hover {
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #layout-container {
   height: 100%;
   width: 100%;
   overflow: auto;
+  min-width: 200px;
 }
 
 /**
  * Common styles for shared components
  */
 
 .grid-container {
   display: flex;
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -766,16 +766,20 @@ var PageStyleActor = protocol.ActorClass
     let clientRect = node.rawNode.getBoundingClientRect();
     layout.width = parseFloat(clientRect.width.toPrecision(6));
     layout.height = parseFloat(clientRect.height.toPrecision(6));
 
     // We compute and update the values of margins & co.
     let style = CssLogic.getComputedStyle(node.rawNode);
     for (let prop of [
       "position",
+      "top",
+      "right",
+      "bottom",
+      "left",
       "margin-top",
       "margin-right",
       "margin-bottom",
       "margin-left",
       "padding-top",
       "padding-right",
       "padding-bottom",
       "padding-left",