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 83669 35d39a331bb8e0671ee18fd68cb0927556f169a6
parent 83668 a60b890c6936cd4d31b23d6824c70a1d4db8dd53
child 83670 3c3f90925e20a8c0e57194ac630acaf96c30a9ec
push id21782
push usertim.taubert@gmx.de
push dateTue, 03 Jan 2012 13:44:55 +0000
treeherdermozilla-central@a737cc816eec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, paul
bugs704132
milestone12.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 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;
 }