Index: Source/devtools/front_end/elements/ComputedStyleWidget.js |
diff --git a/Source/devtools/front_end/elements/ComputedStyleWidget.js b/Source/devtools/front_end/elements/ComputedStyleWidget.js |
index 6b6b6bbfb4f2df10d61fec21c1f37184df3d5970..974f2cf5154a034c2d926a0c3d60d958971b54d4 100644 |
--- a/Source/devtools/front_end/elements/ComputedStyleWidget.js |
+++ b/Source/devtools/front_end/elements/ComputedStyleWidget.js |
@@ -58,11 +58,13 @@ WebInspector.ComputedStyleWidget = function(stylesSidebarPane, sharedModel) |
WebInspector.UIString("Show inherited properties"), |
this._showInheritedComputedStylePropertiesSetting)); |
- this._propertiesContainer = this.element.createChild("div", "monospace"); |
- this._propertiesContainer.classList.add("computed-properties"); |
- this._onTracePropertyBound = this._onTraceProperty.bind(this); |
+ this._propertiesOutline = new TreeOutlineInShadow(); |
+ this._propertiesOutline.registerRequiredCSS("elements/computedStyleSidebarPane.css"); |
+ this._propertiesOutline.element.classList.add("monospace", "computed-properties"); |
+ this.element.appendChild(this._propertiesOutline.element); |
this._stylesSidebarPane = stylesSidebarPane; |
+ this._linkifier = new WebInspector.Linkifier(new WebInspector.Linkifier.DefaultCSSFormatter()); |
/** |
* @param {?RegExp} regex |
@@ -89,18 +91,6 @@ WebInspector.ComputedStyleWidget.createSidebarWrapper = function(stylesSidebarPa |
WebInspector.ComputedStyleWidget._propertySymbol = Symbol("property"); |
WebInspector.ComputedStyleWidget.prototype = { |
- /** |
- * @param {!Event} event |
- */ |
- _onTraceProperty: function(event) |
- { |
- var item = event.target.enclosingNodeOrSelfWithClass("computed-style-property"); |
- var property = item && item[WebInspector.ComputedStyleWidget._propertySymbol]; |
- if (!property) |
- return; |
- this._stylesSidebarPane.tracePropertyName(property.name); |
- }, |
- |
_showInheritedComputedStyleChanged: function() |
{ |
this.update(); |
@@ -140,13 +130,16 @@ WebInspector.ComputedStyleWidget.prototype = { |
*/ |
_innerRebuildUpdate: function(nodeStyle, cascades) |
{ |
- this._propertiesContainer.removeChildren(); |
- if (!nodeStyle || !cascades) |
+ this._propertiesOutline.removeChildren(); |
+ this._linkifier.reset(); |
+ var cssModel = this._sharedModel.cssModel(); |
+ if (!nodeStyle || !cascades || !cssModel) |
return; |
var uniqueProperties = nodeStyle.computedStyle.keysArray(); |
uniqueProperties.sort(propertySorter); |
+ var propertyTraces = this._computePropertyTraces(cascades.matched); |
var showInherited = this._showInheritedComputedStylePropertiesSetting.get(); |
for (var i = 0; i < uniqueProperties.length; ++i) { |
var propertyName = uniqueProperties[i]; |
@@ -157,25 +150,37 @@ WebInspector.ComputedStyleWidget.prototype = { |
var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(propertyName); |
if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) |
continue; |
- var item = this._propertiesContainer.createChild("div", "computed-style-property"); |
- item[WebInspector.ComputedStyleWidget._propertySymbol] = { |
+ |
+ var propertyElement = createElement("div"); |
+ propertyElement.classList.add("computed-style-property"); |
+ propertyElement.classList.toggle("computed-style-property-inherited", inherited); |
+ var renderer = new WebInspector.StylesSidebarPropertyRenderer(null, nodeStyle.node, propertyName, /** @type {string} */(propertyValue)); |
+ renderer.setColorHandler(this._processColor.bind(this)); |
+ var propertyNameElement = renderer.renderName(); |
+ propertyNameElement.classList.add("property-name"); |
+ propertyElement.appendChild(propertyNameElement); |
+ var propertyValueElement = renderer.renderValue(); |
+ propertyValueElement.classList.add("property-value"); |
+ propertyElement.appendChild(propertyValueElement); |
+ |
+ var treeElement = new TreeElement(); |
+ treeElement.selectable = false; |
+ treeElement.title = propertyElement; |
+ treeElement[WebInspector.ComputedStyleWidget._propertySymbol] = { |
name: propertyName, |
value: propertyValue |
}; |
- item.classList.toggle("computed-style-property-inherited", inherited); |
- var renderer = new WebInspector.StylesSidebarPropertyRenderer(null, nodeStyle.node, propertyName, /** @type {string} */(propertyValue)); |
- renderer.setColorHandler(this._processColor.bind(this)); |
+ var isOdd = this._propertiesOutline.rootElement().children().length % 2 === 0; |
+ treeElement.listItemElement.classList.toggle("odd-row", isOdd); |
+ this._propertiesOutline.appendChild(treeElement); |
- if (!inherited) { |
- var traceButton = item.createChild("div", "computed-style-trace-button"); |
- traceButton.createChild("div", "glyph"); |
- traceButton.addEventListener("click", this._onTracePropertyBound, false); |
+ var trace = propertyTraces.get(propertyName); |
+ if (trace) { |
+ this._renderPropertyTrace(cssModel, nodeStyle.node, treeElement, trace); |
+ treeElement.listItemElement.addEventListener("mousedown", consumeEvent, false); |
+ treeElement.listItemElement.addEventListener("dblclick", consumeEvent, false); |
+ treeElement.listItemElement.addEventListener("click", handleClick.bind(null, treeElement), false); |
} |
- item.appendChild(renderer.renderName()); |
- item.appendChild(createTextNode(": ")); |
- item.appendChild(renderer.renderValue()); |
- item.appendChild(createTextNode(";")); |
- this._propertiesContainer.appendChild(item); |
} |
this._updateFilter(this._filterRegex); |
@@ -189,6 +194,80 @@ WebInspector.ComputedStyleWidget.prototype = { |
var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName; |
return canonicalName(a).compareTo(canonicalName(b)); |
} |
+ |
+ /** |
+ * @param {!TreeElement} treeElement |
+ * @param {!Event} event |
+ */ |
+ function handleClick(treeElement, event) |
+ { |
+ if (!treeElement.expanded) |
+ treeElement.expand(); |
+ else |
+ treeElement.collapse(); |
+ consumeEvent(event); |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleModel} cssModel |
+ * @param {!WebInspector.DOMNode} node |
+ * @param {!TreeElement} rootTreeElement |
+ * @param {!Array.<!{property: !WebInspector.CSSProperty, overloaded: boolean}>} tracedProperties |
+ */ |
+ _renderPropertyTrace: function(cssModel, node, rootTreeElement, tracedProperties) |
+ { |
+ for (var propertyInfo of tracedProperties) { |
+ var trace = createElement("div"); |
+ trace.classList.add("property-trace"); |
+ if (propertyInfo.overloaded) |
+ trace.classList.add("property-trace-inactive"); |
+ |
+ var renderer = new WebInspector.StylesSidebarPropertyRenderer(null, node, propertyInfo.property.name, /** @type {string} */(propertyInfo.property.value)); |
+ renderer.setColorHandler(this._processColor.bind(this)); |
+ var valueElement = renderer.renderValue(); |
+ valueElement.classList.add("property-trace-value"); |
+ trace.appendChild(valueElement); |
+ |
+ var rule = propertyInfo.property.ownerStyle.parentRule; |
+ if (rule) { |
+ var linkSpan = trace.createChild("span", "trace-link"); |
+ linkSpan.appendChild(WebInspector.StylePropertiesSection.createRuleOriginNode(cssModel, this._linkifier, rule)); |
+ } |
+ |
+ var selectorElement = trace.createChild("span", "property-trace-selector"); |
+ selectorElement.textContent = rule ? rule.selectorText : "element.style"; |
+ selectorElement.title = selectorElement.textContent; |
+ |
+ var traceTreeElement = new TreeElement(); |
+ traceTreeElement.title = trace; |
+ traceTreeElement.selectable = false; |
+ rootTreeElement.appendChild(traceTreeElement); |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.SectionCascade} matchedCascade |
+ * @return {!Map.<string, !Array.<!{property: !WebInspector.CSSProperty, overloaded: boolean}>>} |
+ */ |
+ _computePropertyTraces: function(matchedCascade) |
+ { |
+ var result = new Map(); |
+ var models = matchedCascade.sectionModels(); |
+ for (var model of models) { |
+ var allProperties = model.style().allProperties; |
+ for (var property of allProperties) { |
+ if (!property.activeInStyle() || !model.isPropertyInCascade(property.name)) |
+ continue; |
+ if (!result.has(property.name)) |
+ result.set(property.name, []); |
+ result.get(property.name).push({ |
+ property: property, |
+ overloaded: model.isPropertyOverloaded(property.name) |
+ }); |
+ } |
+ } |
+ return result; |
}, |
/** |
@@ -206,11 +285,11 @@ WebInspector.ComputedStyleWidget.prototype = { |
*/ |
_updateFilter: function(regex) |
{ |
- for (var i = 0; i < this._propertiesContainer.children.length; ++i) { |
- var item = this._propertiesContainer.children[i]; |
- var property = item[WebInspector.ComputedStyleWidget._propertySymbol]; |
+ var children = this._propertiesOutline.rootElement().children(); |
+ for (var child of children) { |
+ var property = child[WebInspector.ComputedStyleWidget._propertySymbol]; |
var matched = !regex || regex.test(property.name) || regex.test(property.value); |
- item.classList.toggle("hidden", !matched); |
+ child.hidden = !matched; |
} |
}, |