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/CSSImportRule.h" | 9 #include "core/css/CSSImportRule.h" |
10 #include "core/css/CSSMediaRule.h" | 10 #include "core/css/CSSMediaRule.h" |
11 #include "core/css/CSSRuleList.h" | 11 #include "core/css/CSSStyleRule.h" |
12 #include "core/css/MediaList.h" | 12 #include "core/css/MediaList.h" |
13 #include "core/dom/NodeComputedStyle.h" | 13 #include "core/dom/NodeComputedStyle.h" |
14 #include "core/dom/StaticNodeList.h" | 14 #include "core/dom/StaticNodeList.h" |
15 #include "core/frame/FrameView.h" | 15 #include "core/frame/FrameView.h" |
16 #include "core/inspector/InspectorCSSAgent.h" | 16 #include "core/inspector/InspectorCSSAgent.h" |
17 #include "core/inspector/InspectorDOMAgent.h" | 17 #include "core/inspector/InspectorDOMAgent.h" |
18 #include "core/inspector/InspectorHighlight.h" | 18 #include "core/inspector/InspectorHighlight.h" |
19 #include "core/layout/LayoutBox.h" | 19 #include "core/layout/LayoutBox.h" |
20 #include "core/layout/LayoutInline.h" | 20 #include "core/layout/LayoutInline.h" |
21 #include "core/layout/LayoutObject.h" | 21 #include "core/layout/LayoutObject.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 } | 138 } |
139 | 139 |
140 float toValidValue(CSSPropertyID propertyId, float newValue) | 140 float toValidValue(CSSPropertyID propertyId, float newValue) |
141 { | 141 { |
142 if (CSSPropertyPaddingBottom <= propertyId && propertyId <= CSSPropertyPaddi ngTop) | 142 if (CSSPropertyPaddingBottom <= propertyId && propertyId <= CSSPropertyPaddi ngTop) |
143 return newValue >= 0 ? newValue : 0; | 143 return newValue >= 0 ? newValue : 0; |
144 | 144 |
145 return newValue; | 145 return newValue; |
146 } | 146 } |
147 | 147 |
148 bool comparePairs(const std::pair<unsigned, CSSStyleRule*>& lhs, const std::pair <unsigned, CSSStyleRule*>& rhs) | |
149 { | |
150 return lhs.first < rhs.first; | |
151 } | |
152 | |
153 InspectorHighlightConfig affectedNodesHighlightConfig() | 148 InspectorHighlightConfig affectedNodesHighlightConfig() |
154 { | 149 { |
155 // TODO: find a better color | 150 // TODO: find a better color |
156 InspectorHighlightConfig config; | 151 InspectorHighlightConfig config; |
157 config.content = Color(95, 127, 162, 100); | 152 config.content = Color(95, 127, 162, 100); |
158 config.padding = Color(95, 127, 162, 100); | 153 config.padding = Color(95, 127, 162, 100); |
159 config.margin = Color(95, 127, 162, 100); | 154 config.margin = Color(95, 127, 162, 100); |
160 return config; | 155 return config; |
161 } | 156 } |
162 | 157 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 void LayoutEditor::selectNode(Node* node) | 219 void LayoutEditor::selectNode(Node* node) |
225 { | 220 { |
226 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ; | 221 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ; |
227 if (element == m_element) | 222 if (element == m_element) |
228 return; | 223 return; |
229 | 224 |
230 ASSERT(!m_isDirty); | 225 ASSERT(!m_isDirty); |
231 m_element = element; | 226 m_element = element; |
232 m_changingProperty = CSSPropertyInvalid; | 227 m_changingProperty = CSSPropertyInvalid; |
233 m_propertyInitialValue = 0; | 228 m_propertyInitialValue = 0; |
234 initializeCSSRules(); | 229 m_matchedRules = m_cssAgent->matchedRulesList(m_element.get()); |
230 m_currentRuleIndex = m_matchedRules ? m_matchedRules->length() : 0; | |
235 } | 231 } |
236 | 232 |
237 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const | 233 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const |
238 { | 234 { |
239 if (!m_element) | 235 if (!m_element) |
240 return nullptr; | 236 return nullptr; |
241 | 237 |
242 FloatQuad content, padding, border, margin; | 238 FloatQuad content, padding, border, margin; |
243 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin); | 239 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin); |
244 FloatQuad orthogonals = orthogonalVectors(padding); | 240 FloatQuad orthogonals = orthogonalVectors(padding); |
(...skipping 13 matching lines...) Expand all Loading... | |
258 appendAnchorFor(anchors.get(), "margin", "margin-right", marginHandles.p2(), orthogonals.p2()); | 254 appendAnchorFor(anchors.get(), "margin", "margin-right", marginHandles.p2(), orthogonals.p2()); |
259 appendAnchorFor(anchors.get(), "margin", "margin-bottom", marginHandles.p3() , orthogonals.p3()); | 255 appendAnchorFor(anchors.get(), "margin", "margin-bottom", marginHandles.p3() , orthogonals.p3()); |
260 appendAnchorFor(anchors.get(), "margin", "margin-left", marginHandles.p4(), orthogonals.p4()); | 256 appendAnchorFor(anchors.get(), "margin", "margin-left", marginHandles.p4(), orthogonals.p4()); |
261 | 257 |
262 object->setArray("anchors", anchors.release()); | 258 object->setArray("anchors", anchors.release()); |
263 return object.release(); | 259 return object.release(); |
264 } | 260 } |
265 | 261 |
266 RefPtrWillBeRawPtr<CSSPrimitiveValue> LayoutEditor::getPropertyCSSValue(CSSPrope rtyID property) const | 262 RefPtrWillBeRawPtr<CSSPrimitiveValue> LayoutEditor::getPropertyCSSValue(CSSPrope rtyID property) const |
267 { | 263 { |
268 RefPtrWillBeRawPtr<CSSStyleDeclaration> style = m_cssAgent->findEffectiveDec laration(m_element.get(), property); | 264 RefPtrWillBeRawPtr<CSSStyleDeclaration> style = m_cssAgent->findEffectiveDec laration(property, m_matchedRules.get(), m_element->style()); |
269 if (!style) | 265 if (!style) |
270 return nullptr; | 266 return nullptr; |
271 | 267 |
272 RefPtrWillBeRawPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(p roperty); | 268 RefPtrWillBeRawPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(p roperty); |
273 if (!cssValue || !cssValue->isPrimitiveValue()) | 269 if (!cssValue || !cssValue->isPrimitiveValue()) |
274 return nullptr; | 270 return nullptr; |
275 | 271 |
276 return toCSSPrimitiveValue(cssValue.get()); | 272 return toCSSPrimitiveValue(cssValue.get()); |
277 } | 273 } |
278 | 274 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 default: | 321 default: |
326 ASSERT_NOT_REACHED(); | 322 ASSERT_NOT_REACHED(); |
327 break; | 323 break; |
328 } | 324 } |
329 m_propertyInitialValue = cssValue ? cssValue->getFloatValue() : 0; | 325 m_propertyInitialValue = cssValue ? cssValue->getFloatValue() : 0; |
330 } | 326 } |
331 | 327 |
332 void LayoutEditor::overlayPropertyChanged(float cssDelta) | 328 void LayoutEditor::overlayPropertyChanged(float cssDelta) |
333 { | 329 { |
334 if (m_changingProperty && m_factor) { | 330 if (m_changingProperty && m_factor) { |
335 String errorString; | |
336 float newValue = toValidValue(m_changingProperty, cssDelta / m_factor + m_propertyInitialValue); | 331 float newValue = toValidValue(m_changingProperty, cssDelta / m_factor + m_propertyInitialValue); |
337 m_cssAgent->setCSSPropertyValue(&errorString, m_element.get(), m_changin gProperty, truncateZeroes(String::format("%.2f", newValue)) + CSSPrimitiveValue: :unitTypeToString(m_valueUnitType)); | 332 m_isDirty |= setCSSPropertyValueInCurrentRule(truncateZeroes(String::for mat("%.2f", newValue)) + CSSPrimitiveValue::unitTypeToString(m_valueUnitType)); |
338 if (!errorString) | |
339 m_isDirty = true; | |
340 } | 333 } |
341 } | 334 } |
342 | 335 |
343 void LayoutEditor::overlayEndedPropertyChange() | 336 void LayoutEditor::overlayEndedPropertyChange() |
344 { | 337 { |
345 m_changingProperty = CSSPropertyInvalid; | 338 m_changingProperty = CSSPropertyInvalid; |
346 m_propertyInitialValue = 0; | 339 m_propertyInitialValue = 0; |
347 m_factor = 0; | 340 m_factor = 0; |
348 m_valueUnitType = CSSPrimitiveValue::UnitType::Unknown; | 341 m_valueUnitType = CSSPrimitiveValue::UnitType::Unknown; |
349 } | 342 } |
350 | 343 |
351 void LayoutEditor::clearSelection(bool commitChanges) | 344 void LayoutEditor::clearSelection(bool commitChanges) |
352 { | 345 { |
353 ErrorString errorString; | 346 ErrorString errorString; |
354 if (commitChanges) | 347 if (commitChanges) |
355 m_domAgent->markUndoableState(&errorString); | 348 m_domAgent->markUndoableState(&errorString); |
356 else if (m_isDirty) | 349 else if (m_isDirty) |
357 m_domAgent->undo(&errorString); | 350 m_domAgent->undo(&errorString); |
358 | 351 |
359 m_element.clear(); | 352 m_element.clear(); |
360 m_isDirty = false; | 353 m_isDirty = false; |
361 m_matchedRules.clear(); | 354 m_matchedRules.clear(); |
362 m_cachedSelectorsInfo.clear(); | 355 m_cachedSelectorsInfo.clear(); |
363 m_currentRuleIndex = -1; | 356 m_currentRuleIndex = 0; |
364 } | 357 } |
365 | 358 |
366 void LayoutEditor::initializeCSSRules() | 359 bool LayoutEditor::currentStyleIsInline() |
367 { | 360 { |
368 if (!m_element) | 361 return m_currentRuleIndex == (m_matchedRules ? m_matchedRules->length() : 0) ; |
369 return; | 362 } |
370 | |
371 Document* ownerDocument = m_element->ownerDocument(); | |
372 // A non-active document has no styles. | |
373 if (!ownerDocument->isActive()) | |
374 return; | |
375 | |
376 // Matched rules. | |
377 StyleResolver& styleResolver = ownerDocument->ensureStyleResolver(); | |
378 PseudoId elementPseudoId = m_element->pseudoId(); | |
379 m_element->updateDistribution(); | |
380 RefPtrWillBeRawPtr<CSSRuleList> matchedRules = styleResolver.pseudoCSSRulesF orElement(m_element.get(), elementPseudoId, StyleResolver::AllCSSRules); | |
381 if (!matchedRules) | |
382 return; | |
383 | |
384 HashSet<CSSStyleRule*> uniqRulesSet; | |
385 Vector<CSSStyleRule*> uniqRules; | |
386 for (unsigned i = matchedRules->length(); i > 0; --i) { | |
387 CSSRule* rule = matchedRules->item(i); | |
388 if (!rule || rule->type() != CSSRule::STYLE_RULE || !rule->parentStyleSh eet()) | |
389 continue; | |
390 | |
391 CSSStyleRule* styleRule = toCSSStyleRule(rule); | |
392 | |
393 if (uniqRulesSet.contains(styleRule)) | |
394 continue; | |
395 uniqRulesSet.add(styleRule); | |
396 uniqRules.append(styleRule); | |
397 } | |
398 Vector<std::pair<unsigned, CSSStyleRule*>> selectors; | |
399 for (unsigned i = 0; i < uniqRules.size(); ++i) { | |
400 TrackExceptionState exceptionState; | |
401 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySel ectorAll(AtomicString(uniqRules[i]->selectorText()), exceptionState); | |
402 unsigned length = exceptionState.hadException() ? 0: elements->length(); | |
403 selectors.append(std::make_pair(length, uniqRules[i])); | |
404 } | |
405 | |
406 std::sort(selectors.begin(), selectors.end(), &comparePairs); | |
407 for (size_t i = 0; i < selectors.size(); ++i) | |
408 m_matchedRules.append(selectors[i].second); | |
409 }; | |
410 | 363 |
411 void LayoutEditor::nextSelector() | 364 void LayoutEditor::nextSelector() |
412 { | 365 { |
413 if (static_cast<size_t>(m_currentRuleIndex + 1) == m_matchedRules.size()) | 366 if (m_currentRuleIndex == 0) |
367 return; | |
368 | |
369 m_currentRuleIndex--; | |
370 } | |
371 | |
372 void LayoutEditor::previousSelector() | |
373 { | |
374 if (currentStyleIsInline()) | |
414 return; | 375 return; |
415 | 376 |
416 m_currentRuleIndex++; | 377 m_currentRuleIndex++; |
417 } | 378 } |
418 | 379 |
419 void LayoutEditor::previousSelector() | |
420 { | |
421 if (m_currentRuleIndex == -1) | |
422 return; | |
423 | |
424 m_currentRuleIndex--; | |
425 } | |
426 | |
427 String LayoutEditor::currentSelectorInfo() | 380 String LayoutEditor::currentSelectorInfo() |
428 { | 381 { |
429 if (!m_element) | 382 if (!m_element) |
430 return String(); | 383 return String(); |
431 | 384 |
432 if (m_cachedSelectorsInfo.contains(m_currentRuleIndex)) | 385 if (m_cachedSelectorsInfo.contains(m_currentRuleIndex)) |
433 return m_cachedSelectorsInfo.get(m_currentRuleIndex); | 386 return m_cachedSelectorsInfo.get(m_currentRuleIndex); |
434 | 387 |
435 RefPtr<JSONObject> object = JSONObject::create(); | 388 RefPtr<JSONObject> object = JSONObject::create(); |
436 String currentSelectorText = m_currentRuleIndex == -1 ? "inline style" : m_m atchedRules[m_currentRuleIndex]->selectorText(); | 389 String currentSelectorText = currentStyleIsInline() ? "inline style" : toCSS StyleRule(m_matchedRules->item(m_currentRuleIndex))->selectorText(); |
437 object->setString("selector", currentSelectorText); | 390 object->setString("selector", currentSelectorText); |
438 | 391 |
439 Document* ownerDocument = m_element->ownerDocument(); | 392 Document* ownerDocument = m_element->ownerDocument(); |
440 if (!ownerDocument->isActive() || m_currentRuleIndex == -1) | 393 if (!ownerDocument->isActive() || currentStyleIsInline()) |
441 return object->toJSONString(); | 394 return object->toJSONString(); |
442 | 395 |
443 if (m_currentRuleIndex != -1) { | 396 bool hasSameSelectors = false; |
444 bool hasSameSelectors = false; | 397 for (unsigned i = 0; i < m_matchedRules->length(); i++) { |
445 for (size_t i = 0; i < m_matchedRules.size(); i++) { | 398 if (i != m_currentRuleIndex && toCSSStyleRule(m_matchedRules->item(i))-> selectorText() == currentSelectorText) { |
446 if (i != static_cast<unsigned>(m_currentRuleIndex) && m_matchedRules [i]->selectorText() == currentSelectorText) { | 399 hasSameSelectors = true; |
447 hasSameSelectors = true; | 400 break; |
448 break; | |
449 } | |
450 } | |
451 | |
452 if (hasSameSelectors) { | |
453 Vector<String> medias; | |
454 buildMediaListChain(m_matchedRules[m_currentRuleIndex].get(), medias ); | |
455 RefPtr<JSONArray> mediasJSONArray = JSONArray::create(); | |
456 for (size_t i = 0; i < medias.size(); ++i) | |
457 mediasJSONArray->pushString(medias[i]); | |
458 | |
459 object->setArray("medias", mediasJSONArray.release()); | |
460 } | 401 } |
461 } | 402 } |
462 | 403 |
404 if (hasSameSelectors) { | |
405 Vector<String> medias; | |
406 buildMediaListChain(m_matchedRules->item(m_currentRuleIndex), medias); | |
407 RefPtr<JSONArray> mediasJSONArray = JSONArray::create(); | |
408 for (size_t i = 0; i < medias.size(); ++i) | |
409 mediasJSONArray->pushString(medias[i]); | |
410 | |
411 object->setArray("medias", mediasJSONArray.release()); | |
412 } | |
413 | |
463 TrackExceptionState exceptionState; | 414 TrackExceptionState exceptionState; |
464 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelecto rAll(AtomicString(m_matchedRules[m_currentRuleIndex]->selectorText()), exception State); | 415 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelecto rAll(AtomicString(currentSelectorText), exceptionState); |
465 | 416 |
466 if (!elements || exceptionState.hadException()) | 417 if (!elements || exceptionState.hadException()) |
467 return object->toJSONString(); | 418 return object->toJSONString(); |
468 | 419 |
469 RefPtr<JSONArray> highlights = JSONArray::create(); | 420 RefPtr<JSONArray> highlights = JSONArray::create(); |
470 InspectorHighlightConfig config = affectedNodesHighlightConfig(); | 421 InspectorHighlightConfig config = affectedNodesHighlightConfig(); |
471 for (unsigned i = 0; i < elements->length(); ++i) { | 422 for (unsigned i = 0; i < elements->length(); ++i) { |
472 Element* element = elements->item(i); | 423 Element* element = elements->item(i); |
473 if (element == m_element) | 424 if (element == m_element) |
474 continue; | 425 continue; |
475 | 426 |
476 InspectorHighlight highlight(element, config, false); | 427 InspectorHighlight highlight(element, config, false); |
477 highlights->pushObject(highlight.asJSONObject()); | 428 highlights->pushObject(highlight.asJSONObject()); |
478 } | 429 } |
479 | 430 |
480 object->setArray("nodes", highlights.release()); | 431 object->setArray("nodes", highlights.release()); |
481 m_cachedSelectorsInfo.add(m_currentRuleIndex, object->toJSONString()); | 432 m_cachedSelectorsInfo.add(m_currentRuleIndex, object->toJSONString()); |
482 return m_cachedSelectorsInfo.get(m_currentRuleIndex); | 433 return m_cachedSelectorsInfo.get(m_currentRuleIndex); |
483 } | 434 } |
484 | 435 |
436 bool LayoutEditor::setCSSPropertyValueInCurrentRule(const String& value) | |
437 { | |
438 if (!m_element) | |
439 return false; | |
440 | |
441 RefPtrWillBeRawPtr<CSSStyleDeclaration> effectiveDeclaration = m_cssAgent->f indEffectiveDeclaration(m_changingProperty, m_matchedRules.get(), m_element->sty le()); | |
442 | |
443 CSSStyleRule* effectiveRule = nullptr; | |
444 if (effectiveDeclaration && effectiveDeclaration->parentRule() && effectiveD eclaration->parentRule()->type() == CSSRule::STYLE_RULE) | |
445 effectiveRule = toCSSStyleRule(effectiveDeclaration->parentRule()); | |
446 | |
447 String longhand = getPropertyNameString(m_changingProperty); | |
448 bool forceImportant = effectiveDeclaration && effectiveDeclaration->getPrope rtyPriority(longhand) == "important"; | |
449 | |
450 unsigned size = m_matchedRules ? m_matchedRules->length() : 0; | |
dgozman
2015/09/03 23:04:20
Let's make it non-null.
sergeyv
2015/09/03 23:30:27
Done.
| |
451 unsigned effectiveRuleIndex = size; | |
452 if (effectiveDeclaration) { | |
dgozman
2015/09/03 23:04:20
Let's have a single |if (effectiveDeclaration)|.
sergeyv
2015/09/03 23:30:27
Done.
| |
453 for (unsigned i = 0; i < size; ++i) { | |
454 if (m_matchedRules->item(i) == effectiveRule) { | |
455 effectiveRuleIndex = i; | |
456 break; | |
457 } | |
458 } | |
459 } | |
460 | |
461 forceImportant |= effectiveRuleIndex > m_currentRuleIndex; | |
462 CSSStyleDeclaration* style = currentStyleIsInline() ? m_element->style() : t oCSSStyleRule(m_matchedRules->item(m_currentRuleIndex))->style(); | |
463 | |
464 String errorString; | |
465 m_cssAgent->setCSSPropertyValue(&errorString, m_element.get(), style, m_chan gingProperty, value, forceImportant); | |
466 return errorString.isEmpty(); | |
467 } | |
468 | |
485 } // namespace blink | 469 } // namespace blink |
OLD | NEW |