Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: Source/core/inspector/LayoutEditor.cpp

Issue 1310923003: Devtools [LayoutEditor]: Patch values in the selected rule (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@medias
Patch Set: Address comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« Source/core/inspector/InspectorCSSAgent.cpp ('K') | « Source/core/inspector/LayoutEditor.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698