Index: Source/core/inspector/LayoutEditor.cpp |
diff --git a/Source/core/inspector/LayoutEditor.cpp b/Source/core/inspector/LayoutEditor.cpp |
index 8723663dd735be2471e54a60f561f10e6235daa0..a73d6705d131b402d0f89d9eb72f68b8a7035046 100644 |
--- a/Source/core/inspector/LayoutEditor.cpp |
+++ b/Source/core/inspector/LayoutEditor.cpp |
@@ -6,7 +6,9 @@ |
#include "core/inspector/LayoutEditor.h" |
#include "core/css/CSSComputedStyleDeclaration.h" |
+#include "core/css/CSSRuleList.h" |
#include "core/dom/NodeComputedStyle.h" |
+#include "core/dom/StaticNodeList.h" |
#include "core/frame/FrameView.h" |
#include "core/inspector/InspectorCSSAgent.h" |
#include "core/inspector/InspectorDOMAgent.h" |
@@ -139,6 +141,22 @@ float toValidValue(CSSPropertyID propertyId, float newValue) |
return newValue; |
} |
+ |
+bool comparePairs(const std::pair<unsigned, CSSStyleRule*>& lhs, const std::pair<unsigned, CSSStyleRule*>& rhs) |
+{ |
+ return lhs.first < rhs.first; |
+} |
+ |
+InspectorHighlightConfig affectedNodesHighlightConfig() |
+{ |
+ // TODO: find a better color |
+ InspectorHighlightConfig config; |
+ config.content = Color(95, 127, 162, 100); |
+ config.padding = Color(95, 127, 162, 100); |
+ config.margin = Color(95, 127, 162, 100); |
+ return config; |
+} |
+ |
} // namespace |
LayoutEditor::LayoutEditor(InspectorCSSAgent* cssAgent, InspectorDOMAgent* domAgent) |
@@ -156,6 +174,7 @@ DEFINE_TRACE(LayoutEditor) |
visitor->trace(m_element); |
visitor->trace(m_cssAgent); |
visitor->trace(m_domAgent); |
+ visitor->trace(m_matchedRules); |
} |
void LayoutEditor::selectNode(Node* node) |
@@ -168,7 +187,7 @@ void LayoutEditor::selectNode(Node* node) |
m_element = element; |
m_changingProperty = CSSPropertyInvalid; |
m_propertyInitialValue = 0; |
- |
+ initializeCSSRules(); |
} |
PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const |
@@ -223,7 +242,6 @@ PassRefPtr<JSONObject> LayoutEditor::createValueDescription(const String& proper |
object->setNumber("value", cssValue ? cssValue->getFloatValue() : 0); |
CSSPrimitiveValue::UnitType unitType = cssValue ? cssValue->typeWithCalcResolved() : CSSPrimitiveValue::UnitType::Pixels; |
object->setString("unit", CSSPrimitiveValue::unitTypeToString(unitType)); |
- // TODO: Support an editing of other popular units like: em, rem |
object->setBoolean("mutable", isMutableUnitType(unitType)); |
return object.release(); |
} |
@@ -298,6 +316,100 @@ void LayoutEditor::clearSelection(bool commitChanges) |
m_isDirty = false; |
} |
+void LayoutEditor::initializeCSSRules() |
+{ |
+ m_matchedRules.clear(); |
dgozman
2015/09/02 18:58:57
Please also clear rules on commit/discard.
sergeyv
2015/09/02 20:22:18
Done.
|
+ m_currentRuleIndex = -1; |
+ if (!m_element) |
+ return; |
+ |
+ Document* ownerDocument = m_element->ownerDocument(); |
+ // A non-active document has no styles. |
+ if (!ownerDocument->isActive()) |
+ return; |
+ |
+ // Matched rules. |
+ StyleResolver& styleResolver = ownerDocument->ensureStyleResolver(); |
+ PseudoId elementPseudoId = m_element->pseudoId(); |
+ m_element->updateDistribution(); |
+ RefPtrWillBeRawPtr<CSSRuleList> matchedRules = styleResolver.pseudoCSSRulesForElement(m_element.get(), elementPseudoId, StyleResolver::AllCSSRules); |
+ if (!matchedRules) |
+ return; |
+ |
+ HashSet<CSSStyleRule*> uniqRulesSet; |
+ Vector<CSSStyleRule*> uniqRules; |
+ for (unsigned i = matchedRules->length(); i > 0; --i) { |
+ CSSRule* rule = matchedRules->item(i); |
+ if (!rule || rule->type() != CSSRule::STYLE_RULE || !rule->parentStyleSheet()) |
+ continue; |
+ |
+ CSSStyleRule* styleRule = toCSSStyleRule(rule); |
+ if (uniqRulesSet.contains(styleRule)) |
+ continue; |
+ uniqRulesSet.add(styleRule); |
+ uniqRules.append(styleRule); |
+ } |
+ Vector<std::pair<unsigned, CSSStyleRule*>> selectors; |
+ for (unsigned i = 0; i < uniqRules.size(); ++i) { |
+ TrackExceptionState exceptionState; |
+ RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelectorAll(AtomicString(uniqRules[i]->selectorText()), exceptionState); |
+ unsigned length = exceptionState.hadException() ? 0: elements->length(); |
+ selectors.append(std::pair<unsigned, CSSStyleRule*>(length, uniqRules[i])); |
dgozman
2015/09/02 18:58:57
make_pair?
sergeyv
2015/09/02 20:22:18
Done.
|
+ } |
+ |
+ std::sort(selectors.begin(), selectors.end(), &comparePairs); |
+ for (size_t i = 0; i < selectors.size(); ++i) |
+ m_matchedRules.append(selectors[i].second); |
+}; |
+ |
+void LayoutEditor::nextSelector() |
+{ |
+ if (static_cast<size_t>(m_currentRuleIndex + 1) == m_matchedRules.size()) |
+ return; |
+ |
+ m_currentRuleIndex++; |
+} |
+ |
+void LayoutEditor::previousSelector() |
+{ |
+ if (m_currentRuleIndex == -1) |
+ return; |
+ |
+ m_currentRuleIndex--; |
+} |
+ |
+String LayoutEditor::currentSelectorInfo() |
dgozman
2015/09/02 18:58:57
Let's cache the result.
sergeyv
2015/09/02 20:22:18
Done.
|
+{ |
+ if (!m_element) |
+ return emptyString(); |
dgozman
2015/09/02 18:58:57
String()
sergeyv
2015/09/02 20:22:18
Done.
|
+ |
+ RefPtr<JSONObject> object = JSONObject::create(); |
+ String currentSelectorText = m_currentRuleIndex == -1 ? "inline style" : m_matchedRules[m_currentRuleIndex]->selectorText(); |
+ object->setString("selector", currentSelectorText); |
+ |
+ Document* ownerDocument = m_element->ownerDocument(); |
+ if (!ownerDocument->isActive() || m_currentRuleIndex == -1) |
+ return object->toJSONString(); |
+ |
+ TrackExceptionState exceptionState; |
+ RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelectorAll(AtomicString(m_matchedRules[m_currentRuleIndex]->selectorText()), exceptionState); |
+ |
+ if (!elements || exceptionState.hadException()) |
+ return object->toJSONString(); |
+ |
+ RefPtr<JSONArray> highlights = JSONArray::create(); |
+ for (unsigned i = 0; i < elements->length(); ++i) { |
+ Element* element = elements->item(i); |
+ if (element == m_element) |
+ continue; |
+ |
+ InspectorHighlight highlight(element, affectedNodesHighlightConfig(), false); |
dgozman
2015/09/02 18:58:57
nit: extract config into var.
sergeyv
2015/09/02 20:22:18
Done.
|
+ highlights->pushObject(highlight.asJSONObject()); |
+ } |
+ |
+ object->setArray("nodes", highlights.release()); |
+ return object->toJSONString(); |
+} |
} // namespace blink |