Bug 1329068 - Fix layout issue for PropertiesView r?ntim,honza draft
authorRicky Chien <rchien@mozilla.com>
Sun, 15 Jan 2017 14:30:18 +0800
changeset 462869 60bae1617c9ac2792699bf9151c44e516a526d26
parent 462769 80eac484366ad881c6a10bf81e8d9b8f7a676c75
child 463187 ee54959e367d5783f3bcfc5983cf6b9bb04f1ea6
push id41878
push userbmo:rchien@mozilla.com
push dateWed, 18 Jan 2017 03:20:08 +0000
reviewersntim, honza
bugs1329068
milestone53.0a1
Bug 1329068 - Fix layout issue for PropertiesView r?ntim,honza MozReview-Commit-ID: HKW38QrPovm
devtools/client/netmonitor/netmonitor.xul
devtools/client/netmonitor/shared/components/cookies-panel.js
devtools/client/netmonitor/shared/components/headers-panel.js
devtools/client/netmonitor/shared/components/params-panel.js
devtools/client/netmonitor/shared/components/properties-view.js
devtools/client/netmonitor/shared/components/response-panel.js
devtools/client/netmonitor/test/browser_net_post-data-01.js
devtools/client/themes/netmonitor.css
--- a/devtools/client/netmonitor/netmonitor.xul
+++ b/devtools/client/netmonitor/netmonitor.xul
@@ -123,20 +123,18 @@
             <tabpanels flex="1">
               <tabpanel id="headers-tabpanel"
                         class="tabpanel-content">
                 <html:div xmlns="http://www.w3.org/1999/xhtml"
                           id="react-headers-tabpanel-hook"/>
               </tabpanel>
               <tabpanel id="cookies-tabpanel"
                         class="tabpanel-content">
-                <vbox flex="1">
-                  <html:div xmlns="http://www.w3.org/1999/xhtml"
-                      id="react-cookies-tabpanel-hook"/>
-                </vbox>
+                <html:div xmlns="http://www.w3.org/1999/xhtml"
+                    id="react-cookies-tabpanel-hook"/>
               </tabpanel>
               <tabpanel id="params-tabpanel"
                         class="tabpanel-content">
                 <html:div xmlns="http://www.w3.org/1999/xhtml"
                           id="react-params-tabpanel-hook"/>
               </tabpanel>
               <tabpanel id="response-tabpanel"
                         class="tabpanel-content">
--- a/devtools/client/netmonitor/shared/components/cookies-panel.js
+++ b/devtools/client/netmonitor/shared/components/cookies-panel.js
@@ -48,21 +48,23 @@ function CookiesPanel({
   if (response.length) {
     object[RESPONSE_COOKIES] = getProperties(response);
   }
   if (request.length) {
     object[REQUEST_COOKIES] = getProperties(request);
   }
 
   return (
-    PropertiesView({
-      object,
-      filterPlaceHolder: COOKIES_FILTER_TEXT,
-      sectionNames: SECTION_NAMES,
-    })
+    div({ className: "panel-container" },
+      PropertiesView({
+        object,
+        filterPlaceHolder: COOKIES_FILTER_TEXT,
+        sectionNames: SECTION_NAMES,
+      })
+    )
   );
 }
 
 CookiesPanel.displayName = "CookiesPanel";
 
 CookiesPanel.propTypes = {
   request: PropTypes.array.isRequired,
   response: PropTypes.array.isRequired,
--- a/devtools/client/netmonitor/shared/components/headers-panel.js
+++ b/devtools/client/netmonitor/shared/components/headers-panel.js
@@ -197,17 +197,17 @@ const HeadersPanel = createClass({
               }),
             ),
           )
         )
       );
     }
 
     return (
-      div({},
+      div({ className: "panel-container" },
         div({ className: "summary" },
           summaryUrl,
           summaryMethod,
           summaryAddress,
           summaryStatus,
           summaryVersion,
           summaryRawHeaders,
         ),
--- a/devtools/client/netmonitor/shared/components/params-panel.js
+++ b/devtools/client/netmonitor/shared/components/params-panel.js
@@ -87,21 +87,23 @@ function ParamsPanel({
         },
       };
     }
   } else {
     postData = "";
   }
 
   return (
-    PropertiesView({
-      object,
-      filterPlaceHolder: PARAMS_FILTER_TEXT,
-      sectionNames: SECTION_NAMES,
-    })
+    div({ className: "panel-container" },
+      PropertiesView({
+        object,
+        filterPlaceHolder: PARAMS_FILTER_TEXT,
+        sectionNames: SECTION_NAMES,
+      })
+    )
   );
 }
 
 ParamsPanel.displayName = "ParamsPanel";
 
 ParamsPanel.propTypes = {
   formDataSections: PropTypes.array,
   postData: PropTypes.string,
--- a/devtools/client/netmonitor/shared/components/properties-view.js
+++ b/devtools/client/netmonitor/shared/components/properties-view.js
@@ -78,17 +78,17 @@ const PropertiesView = createClass({
   },
 
   renderRowWithEditor(props) {
     const { level, name, value, path } = props.member;
 
     // Display source editor when specifying to EDITOR_CONFIG_ID along with config
     if (level === 1 && name === EDITOR_CONFIG_ID) {
       return (
-        tr({},
+        tr({ className: "editor-row-container" },
           td({ colSpan: 2 },
             Editor(value)
           )
         )
       );
     }
 
     // Skip for editor config
--- a/devtools/client/netmonitor/shared/components/response-panel.js
+++ b/devtools/client/netmonitor/shared/components/response-panel.js
@@ -116,17 +116,17 @@ const ResponsePanel = createClass({
     if (!mimeType || !url || typeof response !== "string") {
       return null;
     }
 
     if (mimeType.includes("image/")) {
       let { width, height } = this.state.imageDimensions;
 
       return (
-        div({ className: "response-image-box devtools-monospace" },
+        div({ className: "panel-container response-image-box devtools-monospace" },
           img({
             className: "response-image",
             src: formDataURI(mimeType, encoding, response),
             onLoad: this.updateImageDimemsions,
           }),
           div({ className: "response-summary" },
             div({ className: "tabpanel-summary-label" }, RESPONSE_IMG_NAME),
             div({ className: "tabpanel-summary-value" }, getUrlBaseName(url)),
@@ -162,17 +162,17 @@ const ResponsePanel = createClass({
         EDITOR_CONFIG: {
           text: response,
           mode: mimeType.replace(/;.+/, ""),
         },
       };
     }
 
     return (
-      div({},
+      div({ className: "panel-container" },
         error && div({ className: "response-error-header", title: error },
           error
         ),
         PropertiesView({
           object,
           filterPlaceHolder: JSON_FILTER_TEXT,
           sectionNames: [sectionName],
         }),
--- a/devtools/client/netmonitor/test/browser_net_post-data-01.js
+++ b/devtools/client/netmonitor/test/browser_net_post-data-01.js
@@ -5,16 +5,19 @@
 
 /**
  * Tests if the POST requests display the correct information in the UI.
  */
 
 add_task(function* () {
   let { L10N } = require("devtools/client/netmonitor/l10n");
 
+  // Set a higher panel height in order to get full CodeMirror content
+  Services.prefs.setIntPref("devtools.toolbox.footer.height", 400);
+
   let { tab, monitor } = yield initNetMonitor(POST_DATA_URL);
   info("Starting test... ");
 
   let { document, NetMonitorView } = monitor.panelWin;
   let { RequestsMenu } = NetMonitorView;
 
   RequestsMenu.lazyUpdate = false;
 
--- a/devtools/client/themes/netmonitor.css
+++ b/devtools/client/themes/netmonitor.css
@@ -1072,18 +1072,19 @@
 
 /* Responsive sidebar */
 @media (max-width: 700px) {
   :root[platform="linux"] .requests-menu-header-button {
     font-size: 85%;
   }
 }
 
-/* Overwrite tree-view cell colon and use l10n string instead */
-.treeTable .treeLabelCell::after {
+/* Overwrite tree-view cell colon `:` for security panel and tree section */
+#security-tabpanel .treeTable .treeLabelCell::after,
+.treeTable .tree-section .treeLabelCell::after {
   content: "";
 }
 
 /* Layout additional warning icon in tree value cell  */
 .security-info-value {
   display: flex;
 }
 
@@ -1095,28 +1096,27 @@
   width: 100%;
 }
 
 .treeTable .textbox-input:focus {
   outline: 0;
   box-shadow: var(--theme-focus-box-shadow-textbox);
 }
 
+.panel-container {
+  /* FIXME: To avoid the issue which panel exceeds visible range,
+   * we set view heigh - 24px * 2 for toolbox height + tabs height */
+  height: calc(100vh - 48px);
+}
+
+.panel-container,
 .properties-view {
-  /* FIXME: Minus 24px * 2 for toolbox height + panel height
-   * Give a fixed panel container height in order to force tree view scrollable */
-  height: calc(100vh - 48px);
   display: flex;
   flex-direction: column;
-}
-
-#headers-tabpanel .properties-view {
-  /* FIXME: Minus 24px * 2 + 87.5 for toolbox height + panel height + headers summary
-   * Give a fixed panel container height in order to force tree view scrollable */
-  height: calc(100vh - 135.5px);
+  flex-grow: 1;
 }
 
 .properties-view .searchbox-section {
   flex: 0 1 auto;
 }
 
 .properties-view .devtools-searchbox {
   padding: 0;
@@ -1137,16 +1137,46 @@
   display: block;
   overflow-y: auto;
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
 }
 
+/* Apply flex to table tbody in order to fill available vertical space */
+.tree-container .treeTable tbody {
+  display: flex;
+  flex-direction: column;
+  /* Apply flex to table will create an anonymous table element outside of tbody
+   * See also http://stackoverflow.com/a/30851678
+   * Therefore, we set height with this magic number in order to remove the
+   * redundant scrollbar when source editor appears.
+   */
+  height: calc(100% - 3px);
+}
+
+.tree-container .treeTable tr {
+  display: block;
+}
+
+/* Make right td fill available horizontal space */
+.tree-container .treeTable td:last-child {
+  width: 100%;
+}
+
+/* If there is a source editor shows up in the last row of TreeView,
+ * it should occupy the available vertical space.
+ */
+.tree-container .treeTable .editor-row-container,
+.tree-container .treeTable tr:last-child td[colspan="2"] {
+  display: block;
+  height: 100%;
+}
+
 .properties-view .devtools-searchbox,
 .tree-container .treeTable .tree-section {
   width: 100%;
   background-color: var(--theme-toolbar-background);
 }
 
 .properties-view .devtools-searchbox,
 .tree-container .treeTable tr:not(:last-child) td:not([class=""]) {
@@ -1273,33 +1303,25 @@
  * This workaround should be removed after netmonitor is migrated to react
  */
 #react-cookies-tabpanel-hook,
 #react-headers-tabpanel-hook,
 #react-params-tabpanel-hook,
 #react-preview-tabpanel-hook,
 #react-response-tabpanel-hook,
 #react-security-tabpanel-hook,
-#react-timings-tabpanel-hook,
+#react-timings-tabpanel-hook {
+  display: flex;
+  -moz-box-flex: 1;
+  -moz-box-orient: vertical;
+}
+
 #network-statistics-charts,
 #primed-cache-chart,
 #empty-cache-chart {
   display: -moz-box;
   -moz-box-flex: 1;
 }
 
-/* For vbox */
-#react-cookies-tabpanel-hook,
-#react-headers-tabpanel-hook,
-#react-params-tabpanel-hook,
-#react-preview-tabpanel-hook,
-#react-response-tabpanel-hook,
-#react-security-tabpanel-hook,
-#react-timings-tabpanel-hook,
-#primed-cache-chart,
-#empty-cache-chart {
-  -moz-box-orient: vertical;
-}
-
 #primed-cache-chart,
 #empty-cache-chart {
   -moz-box-pack: center;
 }