Bug 704132 - Style Inspector's left column should auto-fit text contents. r=dao r=paul
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Mon, 19 Dec 2011 14:16:43 +0100
changeset 84894 35d39a331bb8e0671ee18fd68cb0927556f169a6
parent 84893 a60b890c6936cd4d31b23d6824c70a1d4db8dd53
child 84895 3c3f90925e20a8c0e57194ac630acaf96c30a9ec
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, paul
bugs704132
milestone12.0a1
Bug 704132 - Style Inspector's left column should auto-fit text contents. r=dao r=paul
browser/devtools/styleinspector/CssHtmlTree.jsm
browser/devtools/styleinspector/csshtmltree.xul
browser/themes/gnomestripe/devtools/csshtmltree.css
browser/themes/pinstripe/devtools/csshtmltree.css
browser/themes/winstripe/devtools/csshtmltree.css
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -284,17 +284,18 @@ CssHtmlTree.prototype = {
       let fragment = this.doc.createDocumentFragment();
       this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
         onItem: function(aPropertyName) {
           // Per-item callback.
           if (this.viewedElement != aElement || !this.styleInspector.isOpen()) {
             return false;
           }
           let propView = new PropertyView(this, aPropertyName);
-          fragment.appendChild(propView.build());
+          fragment.appendChild(propView.buildMain());
+          fragment.appendChild(propView.buildSelectorContainer());
           if (propView.visible) {
             this.numVisibleProperties++;
           }
           propView.refreshAllSelectors();
           this.propertyViews.push(propView);
         }.bind(this),
         onDone: function() {
           // Completed callback.
@@ -606,109 +607,134 @@ PropertyView.prototype = {
     return true;
   },
 
   /**
    * Returns the className that should be assigned to the propertyView.
    *
    * @return string
    */
-  get className()
+  get propertyHeaderClassName()
   {
     if (this.visible) {
       this.tree._darkStripe = !this.tree._darkStripe;
       let darkValue = this.tree._darkStripe ?
                       "property-view darkrow" : "property-view";
       return darkValue;
     }
     return "property-view-hidden";
   },
 
-  build: function PropertyView_build()
+  /**
+   * Returns the className that should be assigned to the propertyView content
+   * container.
+   * @return string
+   */
+  get propertyContentClassName()
+  {
+    if (this.visible) {
+      let darkValue = this.tree._darkStripe ?
+                      "property-content darkrow" : "property-content";
+      return darkValue;
+    }
+    return "property-content-hidden";
+  },
+
+  buildMain: function PropertyView_buildMain()
   {
     let doc = this.tree.doc;
-    this.element = doc.createElementNS(HTML_NS, "div");
-    this.element.setAttribute("class", this.className);
+    this.element = doc.createElementNS(HTML_NS, "tr");
+    this.element.setAttribute("class", this.propertyHeaderClassName);
+    this.element.addEventListener("click", this.propertyRowClick.bind(this), false);
 
-    this.propertyHeader = doc.createElementNS(XUL_NS, "hbox");
+    this.propertyHeader = doc.createElementNS(HTML_NS, "td");
     this.element.appendChild(this.propertyHeader);
     this.propertyHeader.setAttribute("class", "property-header");
-    this.propertyHeader.addEventListener("click", this.propertyHeaderClick.bind(this), false);
 
     this.matchedExpander = doc.createElementNS(HTML_NS, "div");
     this.propertyHeader.appendChild(this.matchedExpander);
     this.matchedExpander.setAttribute("class", "match expander");
 
     let name = doc.createElementNS(HTML_NS, "div");
     this.propertyHeader.appendChild(name);
     name.setAttribute("class", "property-name");
     name.textContent = this.name;
 
-    let helpcontainer = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(helpcontainer);
+    let helpcontainer = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(helpcontainer);
     helpcontainer.setAttribute("class", "helplink-container");
 
     let helplink = doc.createElementNS(HTML_NS, "a");
     helpcontainer.appendChild(helplink);
     helplink.setAttribute("class", "helplink");
     helplink.setAttribute("title", CssHtmlTree.HELP_LINK_TITLE);
     helplink.textContent = CssHtmlTree.HELP_LINK_TITLE;
     helplink.addEventListener("click", this.mdnLinkClick.bind(this), false);
 
-    this.valueNode = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(this.valueNode);
+    this.valueNode = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(this.valueNode);
     this.valueNode.setAttribute("class", "property-value");
     this.valueNode.setAttribute("dir", "ltr");
     this.valueNode.textContent = this.value;
 
-    this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "div");
-    this.element.appendChild(this.matchedSelectorsContainer);
+    return this.element;
+  },
+
+  buildSelectorContainer: function PropertyView_buildSelectorContainer()
+  {
+    let doc = this.tree.doc;
+    let element = doc.createElementNS(HTML_NS, "tr");
+    element.setAttribute("class", this.propertyContentClassName);
+    this.matchedSelectorsContainer = doc.createElementNS(HTML_NS, "td");
+    this.matchedSelectorsContainer.setAttribute("colspan", "0");
     this.matchedSelectorsContainer.setAttribute("class", "rulelink");
+    element.appendChild(this.matchedSelectorsContainer);
 
-    return this.element;
+    return element;
   },
 
   /**
    * Refresh the panel's CSS property value.
    */
   refresh: function PropertyView_refresh()
   {
-    this.element.className = this.className;
+    this.element.className = this.propertyHeaderClassName;
+    this.element.nextElementSibling.className = this.propertyContentClassName;
 
     if (this.prevViewedElement != this.tree.viewedElement) {
       this._matchedSelectorViews = null;
       this._unmatchedSelectorViews = null;
       this.prevViewedElement = this.tree.viewedElement;
     }
 
     if (!this.tree.viewedElement || !this.visible) {
       this.valueNode.innerHTML = "";
-      this.matchedSelectorsContainer.hidden = true;
+      this.matchedSelectorsContainer.parentNode.hidden = true;
       this.matchedSelectorsContainer.innerHTML = "";
       this.matchedExpander.removeAttribute("open");
       return;
     }
 
     this.tree.numVisibleProperties++;
     this.valueNode.innerHTML = this.propertyInfo.value;
     this.refreshAllSelectors();
   },
 
   /**
    * Refresh the panel matched rules.
    */
   refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors()
   {
     let hasMatchedSelectors = this.hasMatchedSelectors;
-    this.matchedSelectorsContainer.hidden = !hasMatchedSelectors;
+    this.matchedSelectorsContainer.parentNode.hidden = !hasMatchedSelectors;
 
     if (hasMatchedSelectors) {
-      this.propertyHeader.classList.add("expandable");
+      this.propertyHeader.parentNode.classList.add("expandable");
     } else {
-      this.propertyHeader.classList.remove("expandable");
+      this.propertyHeader.parentNode.classList.remove("expandable");
     }
 
     if (this.matchedExpanded && hasMatchedSelectors) {
       CssHtmlTree.processTemplate(this.templateMatchedSelectors,
         this.matchedSelectorsContainer, this);
       this.matchedExpander.setAttribute("open", "");
     } else {
       this.matchedSelectorsContainer.innerHTML = "";
@@ -797,17 +823,17 @@ PropertyView.prototype = {
 
   /**
    * The action when a user expands matched selectors.
    *
    * @param {Event} aEvent Used to determine the class name of the targets click
    * event. If the class name is "helplink" then the event is allowed to bubble
    * to the mdn link icon.
    */
-  propertyHeaderClick: function PropertyView_propertyHeaderClick(aEvent)
+  propertyRowClick: function PropertyView_propertyRowClick(aEvent)
   {
     if (aEvent.target.className != "helplink") {
       this.matchedExpanded = !this.matchedExpanded;
       this.refreshAllSelectors();
       aEvent.preventDefault();
     }
   },
 
--- a/browser/devtools/styleinspector/csshtmltree.xul
+++ b/browser/devtools/styleinspector/csshtmltree.xul
@@ -64,18 +64,18 @@
 <div id="root"></div>
 
 <!-- When no properties are found the following block is displayed. -->
 <div id="noResults" hidden="">
   &noPropertiesFound;
 </div>
 
 <!-- The output from #templateProperty (below) is appended here. -->
-<div id="propertyContainer">
-</div>
+<table id="propertyContainer">
+</table>
 
 <xul:hbox id="footer">
   <xul:label class="legendKey bestmatch">&bestMatch;</xul:label>
   <xul:label class="legendKey matched">&matched;</xul:label>
   <xul:label class="legendKey parentmatch">&parentMatch;</xul:label>
 </xul:hbox>
 <!--
 To visually debug the templates without running firefox, alter the display:none
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css
+++ b/browser/themes/gnomestripe/devtools/csshtmltree.css
@@ -46,170 +46,147 @@
 }
 
 #root {
   display: -moz-box;
 }
 
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   -moz-appearance: treetwisty;
-  -moz-margin-start: 10px;
+  padding-top: 12px;
+  -moz-margin-start: 5px;
   -moz-margin-end: 5px;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }
 
--- a/browser/themes/pinstripe/devtools/csshtmltree.css
+++ b/browser/themes/pinstripe/devtools/csshtmltree.css
@@ -46,172 +46,149 @@
 }
 
 #root {
   display: -moz-box;
 }
 
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   -moz-appearance: treetwisty;
   width: 12px;
   height: 12px;
+  padding-top: 12px;
   -moz-margin-start: 5px;
   -moz-margin-end: 5px;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }
 
--- a/browser/themes/winstripe/devtools/csshtmltree.css
+++ b/browser/themes/winstripe/devtools/csshtmltree.css
@@ -45,172 +45,148 @@
   color: -moz-FieldText;
 }
 
 #root {
   display: -moz-box;
 }
 
 .property-header {
-  padding: 4px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 5px;
-}
-
-.rule-unmatched {
-  cursor: pointer;
-  padding: 2px;
-  -moz-padding-start: 4px;
-  -moz-padding-end: 0;
+  padding: 5px 0;
   white-space: nowrap;
+  vertical-align: text-top;
 }
 
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
 
-.helplink-container {
-  position: relative;
-  top: 2px;
-}
-
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
   -moz-margin-end: 2px;
+  cursor: pointer;
 }
 
-.property-header:not(:hover) > .helplink-container {
+.property-view:not(:hover) > .helplink-container {
   visibility: hidden;
 }
 
-.unmatchedSelectorTable {
-  -moz-margin-start: 15px;
-}
-
 .rulelink {
   color: -moz-dialogtext;
-  -moz-margin-start: 12px;
+  padding: 0;
 }
 
 .expander {
   width: 9px;
   height: 9px;
   -moz-margin-start: 5px;
   -moz-margin-end: 5px;
   background: url("chrome://global/skin/tree/twisty-clsd.png") center center no-repeat;
+  display: inline-block;
+  vertical-align: middle;
 }
 
 .expander[open] {
   background-image: url("chrome://global/skin/tree/twisty-open.png");
 }
 
 .expandable {
   cursor: pointer;
 }
 
 .match {
   visibility: hidden;
 }
 
-.expandable > .match {
+.expandable > .property-header > .match {
   visibility: visible;
 }
 
-.only-unmatched {
-  -moz-margin-start: 0;
-}
-
 .property-name {
   font-size: 12px;
   color: -moz-FieldText;
-  width: 220px;
+  display: inline-block;
 }
 .property-value {
+  padding: 0;
   font-size: 10px;
   color: grey;
+  vertical-align: text-top;
+  width: 100%;
 }
 
-.property-view-hidden {
+.property-view-hidden,
+.property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
-  -moz-padding-start: 15px;
+  padding: 0;
+  -moz-padding-start: 20px;
 }
 
 .bestmatch {
   color: black;
 }
 .matched {
   text-decoration: line-through;
 }
 .parentmatch {
   color: #666;
 }
-.unmatched {
-  color: brown;
-}
 
 #propertyContainer {
   display: -moz-box;
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
   overflow-y: auto;
+  border-collapse: collapse;
 }
 
 .darkrow {
   background-color: rgba(0,0,0,.022);
 }
 
 #noResults {
   font-size: 18px;
   margin-top: 5px;
   text-align: center;
 }
 
 .headerControls {
   color: -moz-dialogtext;
   background-color: -moz-dialog;
-  padding-top: 5px;
 }
 
 .onlyuserstyles {
   cursor: pointer;
   font-size: 11px;
 }
 
-.searchfield {
-  -moz-margin-start: 10px;
-}
-
-.styleinspector-legend {
-  -moz-margin-start: 12px;
-}
-
 #footer {
   border-top: 1px solid -moz-dialog;
 }
 
 .legendKey {
   margin: 0 5px;
 }