| Index: third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
|
| diff --git a/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp b/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
|
| deleted file mode 100644
|
| index 07d650ceb7b9445c49531784489986c02999b803..0000000000000000000000000000000000000000
|
| --- a/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
|
| +++ /dev/null
|
| @@ -1,438 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "core/inspector/LayoutEditor.h"
|
| -
|
| -#include "bindings/core/v8/ScriptController.h"
|
| -#include "core/css/CSSComputedStyleDeclaration.h"
|
| -#include "core/css/CSSImportRule.h"
|
| -#include "core/css/CSSMediaRule.h"
|
| -#include "core/css/CSSStyleRule.h"
|
| -#include "core/css/CSSStyleSheet.h"
|
| -#include "core/css/MediaList.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"
|
| -#include "core/inspector/InspectorHighlight.h"
|
| -#include "core/inspector/protocol/Protocol.h"
|
| -#include "core/style/ComputedStyle.h"
|
| -#include "platform/ScriptForbiddenScope.h"
|
| -
|
| -namespace blink {
|
| -
|
| -namespace {
|
| -
|
| -std::unique_ptr<protocol::DictionaryValue> createAnchor(
|
| - const String& type,
|
| - const String& propertyName,
|
| - std::unique_ptr<protocol::DictionaryValue> valueDescription) {
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - object->setString("type", type);
|
| - object->setString("propertyName", propertyName);
|
| - object->setObject("propertyValue", std::move(valueDescription));
|
| - return object;
|
| -}
|
| -
|
| -std::unique_ptr<protocol::DictionaryValue> pointToJSON(FloatPoint point) {
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - object->setDouble("x", point.x());
|
| - object->setDouble("y", point.y());
|
| - return object;
|
| -}
|
| -
|
| -std::unique_ptr<protocol::DictionaryValue> quadToJSON(FloatQuad& quad) {
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - object->setObject("p1", pointToJSON(quad.p1()));
|
| - object->setObject("p2", pointToJSON(quad.p2()));
|
| - object->setObject("p3", pointToJSON(quad.p3()));
|
| - object->setObject("p4", pointToJSON(quad.p4()));
|
| - return object;
|
| -}
|
| -
|
| -bool isMutableUnitType(CSSPrimitiveValue::UnitType unitType) {
|
| - return unitType == CSSPrimitiveValue::UnitType::Pixels ||
|
| - unitType == CSSPrimitiveValue::UnitType::Ems ||
|
| - unitType == CSSPrimitiveValue::UnitType::Percentage ||
|
| - unitType == CSSPrimitiveValue::UnitType::Rems;
|
| -}
|
| -
|
| -String truncateZeroes(const String& number) {
|
| - if (!number.contains('.'))
|
| - return number;
|
| -
|
| - int removeCount = 0;
|
| - while (number[number.length() - removeCount - 1] == '0')
|
| - removeCount++;
|
| -
|
| - if (number[number.length() - removeCount - 1] == '.')
|
| - removeCount++;
|
| -
|
| - return number.left(number.length() - removeCount);
|
| -}
|
| -
|
| -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;
|
| -}
|
| -
|
| -void collectMediaQueriesFromRule(CSSRule* rule, Vector<String>& mediaArray) {
|
| - MediaList* mediaList;
|
| - if (rule->type() == CSSRule::kMediaRule) {
|
| - CSSMediaRule* mediaRule = toCSSMediaRule(rule);
|
| - mediaList = mediaRule->media();
|
| - } else if (rule->type() == CSSRule::kImportRule) {
|
| - CSSImportRule* importRule = toCSSImportRule(rule);
|
| - mediaList = importRule->media();
|
| - } else {
|
| - mediaList = nullptr;
|
| - }
|
| -
|
| - if (mediaList && mediaList->length())
|
| - mediaArray.append(mediaList->mediaText());
|
| -}
|
| -
|
| -void buildMediaListChain(CSSRule* rule, Vector<String>& mediaArray) {
|
| - while (rule) {
|
| - collectMediaQueriesFromRule(rule, mediaArray);
|
| - if (rule->parentRule()) {
|
| - rule = rule->parentRule();
|
| - } else if (rule->parentStyleSheet()) {
|
| - CSSStyleSheet* styleSheet = rule->parentStyleSheet();
|
| - MediaList* mediaList = styleSheet->media();
|
| - if (mediaList && mediaList->length())
|
| - mediaArray.append(mediaList->mediaText());
|
| -
|
| - rule = styleSheet->ownerRule();
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -float roundValue(float value, CSSPrimitiveValue::UnitType unitType) {
|
| - float roundTo = unitType == CSSPrimitiveValue::UnitType::Pixels ? 1 : 0.05;
|
| - return round(value / roundTo) * roundTo;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -LayoutEditor::LayoutEditor(Element* element,
|
| - InspectorCSSAgent* cssAgent,
|
| - InspectorDOMAgent* domAgent,
|
| - ScriptController* scriptController)
|
| - : m_element(element),
|
| - m_cssAgent(cssAgent),
|
| - m_domAgent(domAgent),
|
| - m_scriptController(scriptController),
|
| - m_changingProperty(CSSPropertyInvalid),
|
| - m_propertyInitialValue(0),
|
| - m_isDirty(false),
|
| - m_matchedStyles(cssAgent->matchingStyles(element)),
|
| - m_currentRuleIndex(0) {}
|
| -
|
| -LayoutEditor::~LayoutEditor() {}
|
| -
|
| -void LayoutEditor::dispose() {
|
| - if (!m_isDirty)
|
| - return;
|
| -
|
| - m_domAgent->undo();
|
| -}
|
| -
|
| -DEFINE_TRACE(LayoutEditor) {
|
| - visitor->trace(m_element);
|
| - visitor->trace(m_cssAgent);
|
| - visitor->trace(m_domAgent);
|
| - visitor->trace(m_scriptController);
|
| - visitor->trace(m_matchedStyles);
|
| -}
|
| -
|
| -void LayoutEditor::rebuild() {
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - std::unique_ptr<protocol::ListValue> anchors = protocol::ListValue::create();
|
| -
|
| - appendAnchorFor(anchors.get(), "padding", "padding-top");
|
| - appendAnchorFor(anchors.get(), "padding", "padding-right");
|
| - appendAnchorFor(anchors.get(), "padding", "padding-bottom");
|
| - appendAnchorFor(anchors.get(), "padding", "padding-left");
|
| -
|
| - appendAnchorFor(anchors.get(), "margin", "margin-top");
|
| - appendAnchorFor(anchors.get(), "margin", "margin-right");
|
| - appendAnchorFor(anchors.get(), "margin", "margin-bottom");
|
| - appendAnchorFor(anchors.get(), "margin", "margin-left");
|
| -
|
| - object->setArray("anchors", std::move(anchors));
|
| -
|
| - FloatQuad content, padding, border, margin;
|
| - InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding,
|
| - &border, &margin);
|
| - object->setObject("contentQuad", quadToJSON(content));
|
| - object->setObject("paddingQuad", quadToJSON(padding));
|
| - object->setObject("marginQuad", quadToJSON(margin));
|
| - object->setObject("borderQuad", quadToJSON(border));
|
| - evaluateInOverlay("showLayoutEditor", std::move(object));
|
| - editableSelectorUpdated(false);
|
| -}
|
| -
|
| -const CSSPrimitiveValue* LayoutEditor::getPropertyCSSValue(
|
| - CSSPropertyID property) const {
|
| - CSSStyleDeclaration* style =
|
| - m_cssAgent->findEffectiveDeclaration(property, m_matchedStyles);
|
| - if (!style)
|
| - return nullptr;
|
| -
|
| - const CSSValue* cssValue = style->getPropertyCSSValueInternal(property);
|
| - if (!cssValue || !cssValue->isPrimitiveValue())
|
| - return nullptr;
|
| -
|
| - return toCSSPrimitiveValue(cssValue);
|
| -}
|
| -
|
| -bool LayoutEditor::growInside(String propertyName,
|
| - const CSSPrimitiveValue* value) {
|
| - FloatQuad content1, padding1, border1, margin1;
|
| - InspectorHighlight::buildNodeQuads(m_element.get(), &content1, &padding1,
|
| - &border1, &margin1);
|
| -
|
| - CSSStyleDeclaration* elementStyle = m_element->style();
|
| - if (!elementStyle)
|
| - return false;
|
| -
|
| - String initialValue = elementStyle->getPropertyValue(propertyName);
|
| - String initialPriority = elementStyle->getPropertyPriority(propertyName);
|
| - String newValue;
|
| - if (value)
|
| - newValue =
|
| - String::format("%f", value->getFloatValue() + 1) +
|
| - CSSPrimitiveValue::unitTypeToString(value->typeWithCalcResolved());
|
| - else
|
| - newValue = "5px";
|
| -
|
| - DummyExceptionStateForTesting exceptionState;
|
| - elementStyle->setProperty(propertyName, newValue, "important",
|
| - exceptionState);
|
| - m_element->ownerDocument()->updateStyleAndLayout();
|
| -
|
| - FloatQuad content2, padding2, border2, margin2;
|
| - InspectorHighlight::buildNodeQuads(m_element.get(), &content2, &padding2,
|
| - &border2, &margin2);
|
| -
|
| - elementStyle->setProperty(propertyName, initialValue, initialPriority,
|
| - exceptionState);
|
| - m_element->ownerDocument()->updateStyleAndLayout();
|
| -
|
| - float eps = 0.0001;
|
| - FloatRect boundingBox1, boundingBox2;
|
| -
|
| - if (propertyName.startsWith("padding")) {
|
| - boundingBox1 = padding1.boundingBox();
|
| - boundingBox2 = padding2.boundingBox();
|
| - } else {
|
| - boundingBox1 = margin1.boundingBox();
|
| - boundingBox2 = margin2.boundingBox();
|
| - }
|
| -
|
| - if (propertyName.endsWith("left"))
|
| - return std::abs(boundingBox1.x() - boundingBox2.x()) < eps;
|
| -
|
| - if (propertyName.endsWith("right"))
|
| - return std::abs(boundingBox1.maxX() - boundingBox2.maxX()) < eps;
|
| -
|
| - if (propertyName.endsWith("top"))
|
| - return std::abs(boundingBox1.y() - boundingBox2.y()) < eps;
|
| -
|
| - if (propertyName.endsWith("bottom"))
|
| - return std::abs(boundingBox1.maxY() - boundingBox2.maxY()) < eps;
|
| - return false;
|
| -}
|
| -
|
| -std::unique_ptr<protocol::DictionaryValue> LayoutEditor::createValueDescription(
|
| - const String& propertyName) {
|
| - const CSSPrimitiveValue* cssValue =
|
| - getPropertyCSSValue(cssPropertyID(propertyName));
|
| - if (cssValue && !(cssValue->isLength() || cssValue->isPercentage()))
|
| - return nullptr;
|
| -
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - object->setDouble("value", cssValue ? cssValue->getFloatValue() : 0);
|
| - CSSPrimitiveValue::UnitType unitType =
|
| - cssValue ? cssValue->typeWithCalcResolved()
|
| - : CSSPrimitiveValue::UnitType::Pixels;
|
| - object->setString("unit", CSSPrimitiveValue::unitTypeToString(unitType));
|
| - object->setBoolean("mutable", isMutableUnitType(unitType));
|
| -
|
| - if (!m_growsInside.contains(propertyName))
|
| - m_growsInside.set(propertyName, growInside(propertyName, cssValue));
|
| -
|
| - object->setBoolean("growInside", m_growsInside.get(propertyName));
|
| - return object;
|
| -}
|
| -
|
| -void LayoutEditor::appendAnchorFor(protocol::ListValue* anchors,
|
| - const String& type,
|
| - const String& propertyName) {
|
| - std::unique_ptr<protocol::DictionaryValue> description =
|
| - createValueDescription(propertyName);
|
| - if (description)
|
| - anchors->pushValue(
|
| - createAnchor(type, propertyName, std::move(description)));
|
| -}
|
| -
|
| -void LayoutEditor::overlayStartedPropertyChange(const String& anchorName) {
|
| - m_changingProperty = cssPropertyID(anchorName);
|
| - if (!m_changingProperty)
|
| - return;
|
| -
|
| - const CSSPrimitiveValue* cssValue = getPropertyCSSValue(m_changingProperty);
|
| - m_valueUnitType = cssValue ? cssValue->typeWithCalcResolved()
|
| - : CSSPrimitiveValue::UnitType::Pixels;
|
| - if (!isMutableUnitType(m_valueUnitType))
|
| - return;
|
| -
|
| - switch (m_valueUnitType) {
|
| - case CSSPrimitiveValue::UnitType::Pixels:
|
| - m_factor = 1;
|
| - break;
|
| - case CSSPrimitiveValue::UnitType::Ems:
|
| - m_factor = m_element->computedStyle()->computedFontSize();
|
| - break;
|
| - case CSSPrimitiveValue::UnitType::Percentage:
|
| - // It is hard to correctly support percentages, so we decided hack it this
|
| - // way: 100% = 1000px
|
| - m_factor = 10;
|
| - break;
|
| - case CSSPrimitiveValue::UnitType::Rems:
|
| - m_factor = m_element->document().computedStyle()->computedFontSize();
|
| - break;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| - break;
|
| - }
|
| - m_propertyInitialValue = cssValue ? cssValue->getFloatValue() : 0;
|
| -}
|
| -
|
| -void LayoutEditor::overlayPropertyChanged(float cssDelta) {
|
| - if (m_changingProperty && m_factor) {
|
| - float newValue = cssDelta / m_factor + m_propertyInitialValue;
|
| - newValue = newValue >= 0 ? roundValue(newValue, m_valueUnitType) : 0;
|
| - m_isDirty |= setCSSPropertyValueInCurrentRule(
|
| - truncateZeroes(String::format("%.2f", newValue)) +
|
| - CSSPrimitiveValue::unitTypeToString(m_valueUnitType));
|
| - }
|
| -}
|
| -
|
| -void LayoutEditor::overlayEndedPropertyChange() {
|
| - m_changingProperty = CSSPropertyInvalid;
|
| - m_propertyInitialValue = 0;
|
| - m_factor = 0;
|
| - m_valueUnitType = CSSPrimitiveValue::UnitType::Unknown;
|
| -}
|
| -
|
| -void LayoutEditor::commitChanges() {
|
| - if (!m_isDirty)
|
| - return;
|
| -
|
| - m_isDirty = false;
|
| - m_domAgent->markUndoableState();
|
| -}
|
| -
|
| -void LayoutEditor::nextSelector() {
|
| - if (m_currentRuleIndex == m_matchedStyles.size() - 1)
|
| - return;
|
| -
|
| - ++m_currentRuleIndex;
|
| - editableSelectorUpdated(true);
|
| -}
|
| -
|
| -void LayoutEditor::previousSelector() {
|
| - if (m_currentRuleIndex == 0)
|
| - return;
|
| -
|
| - --m_currentRuleIndex;
|
| - editableSelectorUpdated(true);
|
| -}
|
| -
|
| -void LayoutEditor::editableSelectorUpdated(bool hasChanged) const {
|
| - CSSStyleDeclaration* style = m_matchedStyles.at(m_currentRuleIndex).get();
|
| - evaluateInOverlay("setSelectorInLayoutEditor", currentSelectorInfo(style));
|
| - if (hasChanged)
|
| - m_cssAgent->layoutEditorItemSelected(m_element.get(), style);
|
| -}
|
| -
|
| -std::unique_ptr<protocol::DictionaryValue> LayoutEditor::currentSelectorInfo(
|
| - CSSStyleDeclaration* style) const {
|
| - std::unique_ptr<protocol::DictionaryValue> object =
|
| - protocol::DictionaryValue::create();
|
| - CSSStyleRule* rule =
|
| - style->parentRule() ? toCSSStyleRule(style->parentRule()) : nullptr;
|
| - String currentSelectorText = rule ? rule->selectorText() : "element.style";
|
| - object->setString("selector", currentSelectorText);
|
| -
|
| - Document* ownerDocument = m_element->ownerDocument();
|
| - if (!ownerDocument->isActive() || !rule)
|
| - return object;
|
| -
|
| - Vector<String> medias;
|
| - buildMediaListChain(rule, medias);
|
| - std::unique_ptr<protocol::ListValue> mediaListValue =
|
| - protocol::ListValue::create();
|
| - for (size_t i = 0; i < medias.size(); ++i)
|
| - mediaListValue->pushValue(protocol::StringValue::create(medias[i]));
|
| -
|
| - object->setArray("medias", std::move(mediaListValue));
|
| -
|
| - DummyExceptionStateForTesting exceptionState;
|
| - StaticElementList* elements = ownerDocument->querySelectorAll(
|
| - AtomicString(currentSelectorText), exceptionState);
|
| -
|
| - if (!elements || exceptionState.hadException())
|
| - return object;
|
| -
|
| - std::unique_ptr<protocol::ListValue> highlights =
|
| - protocol::ListValue::create();
|
| - InspectorHighlightConfig config = affectedNodesHighlightConfig();
|
| - for (unsigned i = 0; i < elements->length(); ++i) {
|
| - Element* element = elements->item(i);
|
| - if (element == m_element)
|
| - continue;
|
| -
|
| - InspectorHighlight highlight(element, config, false);
|
| - highlights->pushValue(highlight.asProtocolValue());
|
| - }
|
| -
|
| - object->setArray("nodes", std::move(highlights));
|
| - return object;
|
| -}
|
| -
|
| -bool LayoutEditor::setCSSPropertyValueInCurrentRule(const String& value) {
|
| - Response response = m_cssAgent->setLayoutEditorValue(
|
| - m_element.get(), m_matchedStyles.at(m_currentRuleIndex),
|
| - m_changingProperty, value, false);
|
| - return response.isSuccess();
|
| -}
|
| -
|
| -void LayoutEditor::evaluateInOverlay(
|
| - const String& method,
|
| - std::unique_ptr<protocol::Value> argument) const {
|
| - ScriptForbiddenScope::AllowUserAgentScript allowScript;
|
| - std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
|
| - command->pushValue(protocol::StringValue::create(method));
|
| - command->pushValue(std::move(argument));
|
| - m_scriptController->executeScriptInMainWorld(
|
| - "dispatch(" + command->serialize() + ")",
|
| - ScriptController::ExecuteScriptWhenScriptsDisabled);
|
| -}
|
| -
|
| -} // namespace blink
|
|
|