OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/inspector/LayoutEditor.h" | 6 #include "core/inspector/LayoutEditor.h" |
7 | 7 |
8 #include "core/css/CSSComputedStyleDeclaration.h" | 8 #include "core/css/CSSComputedStyleDeclaration.h" |
9 #include "core/css/CSSRuleList.h" | |
9 #include "core/dom/NodeComputedStyle.h" | 10 #include "core/dom/NodeComputedStyle.h" |
11 #include "core/dom/StaticNodeList.h" | |
10 #include "core/frame/FrameView.h" | 12 #include "core/frame/FrameView.h" |
11 #include "core/inspector/InspectorCSSAgent.h" | 13 #include "core/inspector/InspectorCSSAgent.h" |
12 #include "core/inspector/InspectorDOMAgent.h" | 14 #include "core/inspector/InspectorDOMAgent.h" |
13 #include "core/inspector/InspectorHighlight.h" | 15 #include "core/inspector/InspectorHighlight.h" |
14 #include "core/layout/LayoutBox.h" | 16 #include "core/layout/LayoutBox.h" |
15 #include "core/layout/LayoutInline.h" | 17 #include "core/layout/LayoutInline.h" |
16 #include "core/layout/LayoutObject.h" | 18 #include "core/layout/LayoutObject.h" |
17 #include "core/style/ComputedStyle.h" | 19 #include "core/style/ComputedStyle.h" |
18 #include "platform/JSONValues.h" | 20 #include "platform/JSONValues.h" |
19 | 21 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 return number.left(number.length() - removeCount); | 134 return number.left(number.length() - removeCount); |
133 } | 135 } |
134 | 136 |
135 float toValidValue(CSSPropertyID propertyId, float newValue) | 137 float toValidValue(CSSPropertyID propertyId, float newValue) |
136 { | 138 { |
137 if (CSSPropertyPaddingBottom <= propertyId && propertyId <= CSSPropertyPaddi ngTop) | 139 if (CSSPropertyPaddingBottom <= propertyId && propertyId <= CSSPropertyPaddi ngTop) |
138 return newValue >= 0 ? newValue : 0; | 140 return newValue >= 0 ? newValue : 0; |
139 | 141 |
140 return newValue; | 142 return newValue; |
141 } | 143 } |
144 | |
145 bool comparePairs(const std::pair<unsigned, CSSStyleRule*>& lhs, const std::pair <unsigned, CSSStyleRule*>& rhs) | |
146 { | |
147 return lhs.first < rhs.first; | |
148 } | |
149 | |
150 InspectorHighlightConfig affectedNodesHighlightConfig() | |
151 { | |
152 // TODO: find a better color | |
153 InspectorHighlightConfig config; | |
154 config.content = Color(95, 127, 162, 100); | |
155 config.padding = Color(95, 127, 162, 100); | |
156 config.margin = Color(95, 127, 162, 100); | |
157 return config; | |
158 } | |
159 | |
142 } // namespace | 160 } // namespace |
143 | 161 |
144 LayoutEditor::LayoutEditor(InspectorCSSAgent* cssAgent, InspectorDOMAgent* domAg ent) | 162 LayoutEditor::LayoutEditor(InspectorCSSAgent* cssAgent, InspectorDOMAgent* domAg ent) |
145 : m_element(nullptr) | 163 : m_element(nullptr) |
146 , m_cssAgent(cssAgent) | 164 , m_cssAgent(cssAgent) |
147 , m_domAgent(domAgent) | 165 , m_domAgent(domAgent) |
148 , m_changingProperty(CSSPropertyInvalid) | 166 , m_changingProperty(CSSPropertyInvalid) |
149 , m_propertyInitialValue(0) | 167 , m_propertyInitialValue(0) |
150 , m_isDirty(false) | 168 , m_isDirty(false) |
151 { | 169 { |
152 } | 170 } |
153 | 171 |
154 DEFINE_TRACE(LayoutEditor) | 172 DEFINE_TRACE(LayoutEditor) |
155 { | 173 { |
156 visitor->trace(m_element); | 174 visitor->trace(m_element); |
157 visitor->trace(m_cssAgent); | 175 visitor->trace(m_cssAgent); |
158 visitor->trace(m_domAgent); | 176 visitor->trace(m_domAgent); |
177 visitor->trace(m_matchedRules); | |
159 } | 178 } |
160 | 179 |
161 void LayoutEditor::selectNode(Node* node) | 180 void LayoutEditor::selectNode(Node* node) |
162 { | 181 { |
163 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ; | 182 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ; |
164 if (element == m_element) | 183 if (element == m_element) |
165 return; | 184 return; |
166 | 185 |
167 ASSERT(!m_isDirty); | 186 ASSERT(!m_isDirty); |
168 m_element = element; | 187 m_element = element; |
169 m_changingProperty = CSSPropertyInvalid; | 188 m_changingProperty = CSSPropertyInvalid; |
170 m_propertyInitialValue = 0; | 189 m_propertyInitialValue = 0; |
171 | 190 initializeCSSRules(); |
172 } | 191 } |
173 | 192 |
174 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const | 193 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const |
175 { | 194 { |
176 if (!m_element) | 195 if (!m_element) |
177 return nullptr; | 196 return nullptr; |
178 | 197 |
179 FloatQuad content, padding, border, margin; | 198 FloatQuad content, padding, border, margin; |
180 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin); | 199 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin); |
181 FloatQuad orthogonals = orthogonalVectors(padding); | 200 FloatQuad orthogonals = orthogonalVectors(padding); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 PassRefPtr<JSONObject> LayoutEditor::createValueDescription(const String& proper tyName) const | 235 PassRefPtr<JSONObject> LayoutEditor::createValueDescription(const String& proper tyName) const |
217 { | 236 { |
218 RefPtrWillBeRawPtr<CSSPrimitiveValue> cssValue = getPropertyCSSValue(cssProp ertyID(propertyName)); | 237 RefPtrWillBeRawPtr<CSSPrimitiveValue> cssValue = getPropertyCSSValue(cssProp ertyID(propertyName)); |
219 if (cssValue && !(cssValue->isLength() || cssValue->isPercentage())) | 238 if (cssValue && !(cssValue->isLength() || cssValue->isPercentage())) |
220 return nullptr; | 239 return nullptr; |
221 | 240 |
222 RefPtr<JSONObject> object = JSONObject::create(); | 241 RefPtr<JSONObject> object = JSONObject::create(); |
223 object->setNumber("value", cssValue ? cssValue->getFloatValue() : 0); | 242 object->setNumber("value", cssValue ? cssValue->getFloatValue() : 0); |
224 CSSPrimitiveValue::UnitType unitType = cssValue ? cssValue->typeWithCalcReso lved() : CSSPrimitiveValue::UnitType::Pixels; | 243 CSSPrimitiveValue::UnitType unitType = cssValue ? cssValue->typeWithCalcReso lved() : CSSPrimitiveValue::UnitType::Pixels; |
225 object->setString("unit", CSSPrimitiveValue::unitTypeToString(unitType)); | 244 object->setString("unit", CSSPrimitiveValue::unitTypeToString(unitType)); |
226 // TODO: Support an editing of other popular units like: em, rem | |
227 object->setBoolean("mutable", isMutableUnitType(unitType)); | 245 object->setBoolean("mutable", isMutableUnitType(unitType)); |
228 return object.release(); | 246 return object.release(); |
229 } | 247 } |
230 | 248 |
231 void LayoutEditor::appendAnchorFor(JSONArray* anchors, const String& type, const String& propertyName, const FloatPoint& position, const FloatPoint& orthogonalV ector) const | 249 void LayoutEditor::appendAnchorFor(JSONArray* anchors, const String& type, const String& propertyName, const FloatPoint& position, const FloatPoint& orthogonalV ector) const |
232 { | 250 { |
233 RefPtr<JSONObject> description = createValueDescription(propertyName); | 251 RefPtr<JSONObject> description = createValueDescription(propertyName); |
234 if (description) | 252 if (description) |
235 anchors->pushObject(createAnchor(position, type, propertyName, orthogona lVector, description.release())); | 253 anchors->pushObject(createAnchor(position, type, propertyName, orthogona lVector, description.release())); |
236 } | 254 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 ErrorString errorString; | 309 ErrorString errorString; |
292 if (commitChanges) | 310 if (commitChanges) |
293 m_domAgent->markUndoableState(&errorString); | 311 m_domAgent->markUndoableState(&errorString); |
294 else if (m_isDirty) | 312 else if (m_isDirty) |
295 m_domAgent->undo(&errorString); | 313 m_domAgent->undo(&errorString); |
296 | 314 |
297 m_element.clear(); | 315 m_element.clear(); |
298 m_isDirty = false; | 316 m_isDirty = false; |
299 } | 317 } |
300 | 318 |
319 void LayoutEditor::initializeCSSRules() | |
320 { | |
321 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.
| |
322 m_currentRuleIndex = -1; | |
323 if (!m_element) | |
324 return; | |
301 | 325 |
326 Document* ownerDocument = m_element->ownerDocument(); | |
327 // A non-active document has no styles. | |
328 if (!ownerDocument->isActive()) | |
329 return; | |
330 | |
331 // Matched rules. | |
332 StyleResolver& styleResolver = ownerDocument->ensureStyleResolver(); | |
333 PseudoId elementPseudoId = m_element->pseudoId(); | |
334 m_element->updateDistribution(); | |
335 RefPtrWillBeRawPtr<CSSRuleList> matchedRules = styleResolver.pseudoCSSRulesF orElement(m_element.get(), elementPseudoId, StyleResolver::AllCSSRules); | |
336 if (!matchedRules) | |
337 return; | |
338 | |
339 HashSet<CSSStyleRule*> uniqRulesSet; | |
340 Vector<CSSStyleRule*> uniqRules; | |
341 for (unsigned i = matchedRules->length(); i > 0; --i) { | |
342 CSSRule* rule = matchedRules->item(i); | |
343 if (!rule || rule->type() != CSSRule::STYLE_RULE || !rule->parentStyleSh eet()) | |
344 continue; | |
345 | |
346 CSSStyleRule* styleRule = toCSSStyleRule(rule); | |
347 | |
348 if (uniqRulesSet.contains(styleRule)) | |
349 continue; | |
350 uniqRulesSet.add(styleRule); | |
351 uniqRules.append(styleRule); | |
352 } | |
353 Vector<std::pair<unsigned, CSSStyleRule*>> selectors; | |
354 for (unsigned i = 0; i < uniqRules.size(); ++i) { | |
355 TrackExceptionState exceptionState; | |
356 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySel ectorAll(AtomicString(uniqRules[i]->selectorText()), exceptionState); | |
357 unsigned length = exceptionState.hadException() ? 0: elements->length(); | |
358 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.
| |
359 } | |
360 | |
361 std::sort(selectors.begin(), selectors.end(), &comparePairs); | |
362 for (size_t i = 0; i < selectors.size(); ++i) | |
363 m_matchedRules.append(selectors[i].second); | |
364 }; | |
365 | |
366 void LayoutEditor::nextSelector() | |
367 { | |
368 if (static_cast<size_t>(m_currentRuleIndex + 1) == m_matchedRules.size()) | |
369 return; | |
370 | |
371 m_currentRuleIndex++; | |
372 } | |
373 | |
374 void LayoutEditor::previousSelector() | |
375 { | |
376 if (m_currentRuleIndex == -1) | |
377 return; | |
378 | |
379 m_currentRuleIndex--; | |
380 } | |
381 | |
382 String LayoutEditor::currentSelectorInfo() | |
dgozman
2015/09/02 18:58:57
Let's cache the result.
sergeyv
2015/09/02 20:22:18
Done.
| |
383 { | |
384 if (!m_element) | |
385 return emptyString(); | |
dgozman
2015/09/02 18:58:57
String()
sergeyv
2015/09/02 20:22:18
Done.
| |
386 | |
387 RefPtr<JSONObject> object = JSONObject::create(); | |
388 String currentSelectorText = m_currentRuleIndex == -1 ? "inline style" : m_m atchedRules[m_currentRuleIndex]->selectorText(); | |
389 object->setString("selector", currentSelectorText); | |
390 | |
391 Document* ownerDocument = m_element->ownerDocument(); | |
392 if (!ownerDocument->isActive() || m_currentRuleIndex == -1) | |
393 return object->toJSONString(); | |
394 | |
395 TrackExceptionState exceptionState; | |
396 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelecto rAll(AtomicString(m_matchedRules[m_currentRuleIndex]->selectorText()), exception State); | |
397 | |
398 if (!elements || exceptionState.hadException()) | |
399 return object->toJSONString(); | |
400 | |
401 RefPtr<JSONArray> highlights = JSONArray::create(); | |
402 for (unsigned i = 0; i < elements->length(); ++i) { | |
403 Element* element = elements->item(i); | |
404 if (element == m_element) | |
405 continue; | |
406 | |
407 InspectorHighlight highlight(element, affectedNodesHighlightConfig(), fa lse); | |
dgozman
2015/09/02 18:58:57
nit: extract config into var.
sergeyv
2015/09/02 20:22:18
Done.
| |
408 highlights->pushObject(highlight.asJSONObject()); | |
409 } | |
410 | |
411 object->setArray("nodes", highlights.release()); | |
412 return object->toJSONString(); | |
413 } | |
302 | 414 |
303 } // namespace blink | 415 } // namespace blink |
OLD | NEW |