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

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: 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
« no previous file with comments | « Source/core/inspector/LayoutEditor.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 197
203 } // namespace 198 } // namespace
204 199
205 LayoutEditor::LayoutEditor(InspectorCSSAgent* cssAgent, InspectorDOMAgent* domAg ent) 200 LayoutEditor::LayoutEditor(InspectorCSSAgent* cssAgent, InspectorDOMAgent* domAg ent)
206 : m_element(nullptr) 201 : m_element(nullptr)
207 , m_cssAgent(cssAgent) 202 , m_cssAgent(cssAgent)
208 , m_domAgent(domAgent) 203 , m_domAgent(domAgent)
209 , m_changingProperty(CSSPropertyInvalid) 204 , m_changingProperty(CSSPropertyInvalid)
210 , m_propertyInitialValue(0) 205 , m_propertyInitialValue(0)
211 , m_isDirty(false) 206 , m_isDirty(false)
212 , m_currentRuleIndex(-1) 207 , m_matchedRules(StaticCSSRuleList::create())
208 , m_currentRuleIndex(0)
213 { 209 {
214 } 210 }
215 211
216 DEFINE_TRACE(LayoutEditor) 212 DEFINE_TRACE(LayoutEditor)
217 { 213 {
218 visitor->trace(m_element); 214 visitor->trace(m_element);
219 visitor->trace(m_cssAgent); 215 visitor->trace(m_cssAgent);
220 visitor->trace(m_domAgent); 216 visitor->trace(m_domAgent);
221 visitor->trace(m_matchedRules); 217 visitor->trace(m_matchedRules);
222 } 218 }
223 219
224 void LayoutEditor::selectNode(Node* node) 220 void LayoutEditor::selectNode(Node* node)
225 { 221 {
226 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ; 222 Element* element = node && node->isElementNode() ? toElement(node) : nullptr ;
227 if (element == m_element) 223 if (element == m_element)
228 return; 224 return;
229 225
230 ASSERT(!m_isDirty); 226 ASSERT(!m_isDirty);
231 m_element = element; 227 m_element = element;
232 m_changingProperty = CSSPropertyInvalid; 228 m_changingProperty = CSSPropertyInvalid;
233 m_propertyInitialValue = 0; 229 m_propertyInitialValue = 0;
234 initializeCSSRules(); 230 m_matchedRules = m_cssAgent->matchedRulesList(m_element.get());
231 m_currentRuleIndex = m_matchedRules->length();
235 } 232 }
236 233
237 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const 234 PassRefPtr<JSONObject> LayoutEditor::buildJSONInfo() const
238 { 235 {
239 if (!m_element) 236 if (!m_element)
240 return nullptr; 237 return nullptr;
241 238
242 FloatQuad content, padding, border, margin; 239 FloatQuad content, padding, border, margin;
243 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin); 240 InspectorHighlight::buildNodeQuads(m_element.get(), &content, &padding, &bor der, &margin);
244 FloatQuad orthogonals = orthogonalVectors(padding); 241 FloatQuad orthogonals = orthogonalVectors(padding);
(...skipping 13 matching lines...) Expand all
258 appendAnchorFor(anchors.get(), "margin", "margin-right", marginHandles.p2(), orthogonals.p2()); 255 appendAnchorFor(anchors.get(), "margin", "margin-right", marginHandles.p2(), orthogonals.p2());
259 appendAnchorFor(anchors.get(), "margin", "margin-bottom", marginHandles.p3() , orthogonals.p3()); 256 appendAnchorFor(anchors.get(), "margin", "margin-bottom", marginHandles.p3() , orthogonals.p3());
260 appendAnchorFor(anchors.get(), "margin", "margin-left", marginHandles.p4(), orthogonals.p4()); 257 appendAnchorFor(anchors.get(), "margin", "margin-left", marginHandles.p4(), orthogonals.p4());
261 258
262 object->setArray("anchors", anchors.release()); 259 object->setArray("anchors", anchors.release());
263 return object.release(); 260 return object.release();
264 } 261 }
265 262
266 RefPtrWillBeRawPtr<CSSPrimitiveValue> LayoutEditor::getPropertyCSSValue(CSSPrope rtyID property) const 263 RefPtrWillBeRawPtr<CSSPrimitiveValue> LayoutEditor::getPropertyCSSValue(CSSPrope rtyID property) const
267 { 264 {
268 RefPtrWillBeRawPtr<CSSStyleDeclaration> style = m_cssAgent->findEffectiveDec laration(m_element.get(), property); 265 RefPtrWillBeRawPtr<CSSStyleDeclaration> style = m_cssAgent->findEffectiveDec laration(property, m_matchedRules.get(), m_element->style());
269 if (!style) 266 if (!style)
270 return nullptr; 267 return nullptr;
271 268
272 RefPtrWillBeRawPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(p roperty); 269 RefPtrWillBeRawPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(p roperty);
273 if (!cssValue || !cssValue->isPrimitiveValue()) 270 if (!cssValue || !cssValue->isPrimitiveValue())
274 return nullptr; 271 return nullptr;
275 272
276 return toCSSPrimitiveValue(cssValue.get()); 273 return toCSSPrimitiveValue(cssValue.get());
277 } 274 }
278 275
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 default: 322 default:
326 ASSERT_NOT_REACHED(); 323 ASSERT_NOT_REACHED();
327 break; 324 break;
328 } 325 }
329 m_propertyInitialValue = cssValue ? cssValue->getFloatValue() : 0; 326 m_propertyInitialValue = cssValue ? cssValue->getFloatValue() : 0;
330 } 327 }
331 328
332 void LayoutEditor::overlayPropertyChanged(float cssDelta) 329 void LayoutEditor::overlayPropertyChanged(float cssDelta)
333 { 330 {
334 if (m_changingProperty && m_factor) { 331 if (m_changingProperty && m_factor) {
335 String errorString;
336 float newValue = toValidValue(m_changingProperty, cssDelta / m_factor + m_propertyInitialValue); 332 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)); 333 m_isDirty |= setCSSPropertyValueInCurrentRule(truncateZeroes(String::for mat("%.2f", newValue)) + CSSPrimitiveValue::unitTypeToString(m_valueUnitType));
338 if (!errorString)
339 m_isDirty = true;
340 } 334 }
341 } 335 }
342 336
343 void LayoutEditor::overlayEndedPropertyChange() 337 void LayoutEditor::overlayEndedPropertyChange()
344 { 338 {
345 m_changingProperty = CSSPropertyInvalid; 339 m_changingProperty = CSSPropertyInvalid;
346 m_propertyInitialValue = 0; 340 m_propertyInitialValue = 0;
347 m_factor = 0; 341 m_factor = 0;
348 m_valueUnitType = CSSPrimitiveValue::UnitType::Unknown; 342 m_valueUnitType = CSSPrimitiveValue::UnitType::Unknown;
349 } 343 }
350 344
351 void LayoutEditor::clearSelection(bool commitChanges) 345 void LayoutEditor::clearSelection(bool commitChanges)
352 { 346 {
353 ErrorString errorString; 347 ErrorString errorString;
354 if (commitChanges) 348 if (commitChanges)
355 m_domAgent->markUndoableState(&errorString); 349 m_domAgent->markUndoableState(&errorString);
356 else if (m_isDirty) 350 else if (m_isDirty)
357 m_domAgent->undo(&errorString); 351 m_domAgent->undo(&errorString);
358 352
359 m_element.clear(); 353 m_element.clear();
360 m_isDirty = false; 354 m_isDirty = false;
361 m_matchedRules.clear(); 355 m_matchedRules = StaticCSSRuleList::create();
362 m_currentRuleIndex = -1; 356 m_currentRuleIndex = 0;
363 } 357 }
364 358
365 void LayoutEditor::initializeCSSRules() 359 bool LayoutEditor::currentStyleIsInline()
366 { 360 {
367 if (!m_element) 361 return m_currentRuleIndex == m_matchedRules->length();
368 return; 362 }
369
370 Document* ownerDocument = m_element->ownerDocument();
371 // A non-active document has no styles.
372 if (!ownerDocument->isActive())
373 return;
374
375 // Matched rules.
376 StyleResolver& styleResolver = ownerDocument->ensureStyleResolver();
377 PseudoId elementPseudoId = m_element->pseudoId();
378 m_element->updateDistribution();
379 RefPtrWillBeRawPtr<CSSRuleList> matchedRules = styleResolver.pseudoCSSRulesF orElement(m_element.get(), elementPseudoId, StyleResolver::AllCSSRules);
380 if (!matchedRules)
381 return;
382
383 HashSet<CSSStyleRule*> uniqRulesSet;
384 Vector<CSSStyleRule*> uniqRules;
385 for (unsigned i = matchedRules->length(); i > 0; --i) {
386 CSSRule* rule = matchedRules->item(i);
387 if (!rule || rule->type() != CSSRule::STYLE_RULE || !rule->parentStyleSh eet())
388 continue;
389
390 CSSStyleRule* styleRule = toCSSStyleRule(rule);
391
392 if (uniqRulesSet.contains(styleRule))
393 continue;
394 uniqRulesSet.add(styleRule);
395 uniqRules.append(styleRule);
396 }
397 Vector<std::pair<unsigned, CSSStyleRule*>> selectors;
398 for (unsigned i = 0; i < uniqRules.size(); ++i) {
399 TrackExceptionState exceptionState;
400 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySel ectorAll(AtomicString(uniqRules[i]->selectorText()), exceptionState);
401 unsigned length = exceptionState.hadException() ? 0: elements->length();
402 selectors.append(std::make_pair(length, uniqRules[i]));
403 }
404
405 std::sort(selectors.begin(), selectors.end(), &comparePairs);
406 for (size_t i = 0; i < selectors.size(); ++i)
407 m_matchedRules.append(selectors[i].second);
408 };
409 363
410 void LayoutEditor::nextSelector() 364 void LayoutEditor::nextSelector()
411 { 365 {
412 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())
413 return; 375 return;
414 376
415 m_currentRuleIndex++; 377 m_currentRuleIndex++;
416 } 378 }
417 379
418 void LayoutEditor::previousSelector()
419 {
420 if (m_currentRuleIndex == -1)
421 return;
422
423 m_currentRuleIndex--;
424 }
425
426 String LayoutEditor::currentSelectorInfo() 380 String LayoutEditor::currentSelectorInfo()
427 { 381 {
428 if (!m_element) 382 if (!m_element)
429 return String(); 383 return String();
430 384
431 RefPtr<JSONObject> object = JSONObject::create(); 385 RefPtr<JSONObject> object = JSONObject::create();
432 String currentSelectorText = m_currentRuleIndex == -1 ? "inline style" : m_m atchedRules[m_currentRuleIndex]->selectorText(); 386 String currentSelectorText = currentStyleIsInline() ? "inline style" : toCSS StyleRule(m_matchedRules->item(m_currentRuleIndex))->selectorText();
433 object->setString("selector", currentSelectorText); 387 object->setString("selector", currentSelectorText);
434 388
435 Document* ownerDocument = m_element->ownerDocument(); 389 Document* ownerDocument = m_element->ownerDocument();
436 if (!ownerDocument->isActive() || m_currentRuleIndex == -1) 390 if (!ownerDocument->isActive() || currentStyleIsInline())
437 return object->toJSONString(); 391 return object->toJSONString();
438 392
439 if (m_currentRuleIndex != -1) { 393 bool hasSameSelectors = false;
440 bool hasSameSelectors = false; 394 for (unsigned i = 0; i < m_matchedRules->length(); i++) {
441 for (size_t i = 0; i < m_matchedRules.size(); i++) { 395 if (i != m_currentRuleIndex && toCSSStyleRule(m_matchedRules->item(i))-> selectorText() == currentSelectorText) {
442 if (i != static_cast<unsigned>(m_currentRuleIndex) && m_matchedRules [i]->selectorText() == currentSelectorText) { 396 hasSameSelectors = true;
443 hasSameSelectors = true; 397 break;
444 break;
445 }
446 }
447
448 if (hasSameSelectors) {
449 Vector<String> medias;
450 buildMediaListChain(m_matchedRules[m_currentRuleIndex].get(), medias );
451 RefPtr<JSONArray> mediasJSONArray = JSONArray::create();
452 for (size_t i = 0; i < medias.size(); ++i)
453 mediasJSONArray->pushString(medias[i]);
454
455 object->setArray("medias", mediasJSONArray.release());
456 } 398 }
457 } 399 }
458 400
401 if (hasSameSelectors) {
402 Vector<String> medias;
403 buildMediaListChain(m_matchedRules->item(m_currentRuleIndex), medias);
404 RefPtr<JSONArray> mediasJSONArray = JSONArray::create();
405 for (size_t i = 0; i < medias.size(); ++i)
406 mediasJSONArray->pushString(medias[i]);
407
408 object->setArray("medias", mediasJSONArray.release());
409 }
410
459 TrackExceptionState exceptionState; 411 TrackExceptionState exceptionState;
460 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelecto rAll(AtomicString(m_matchedRules[m_currentRuleIndex]->selectorText()), exception State); 412 RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelecto rAll(AtomicString(currentSelectorText), exceptionState);
461 413
462 if (!elements || exceptionState.hadException()) 414 if (!elements || exceptionState.hadException())
463 return object->toJSONString(); 415 return object->toJSONString();
464 416
465 RefPtr<JSONArray> highlights = JSONArray::create(); 417 RefPtr<JSONArray> highlights = JSONArray::create();
466 InspectorHighlightConfig config = affectedNodesHighlightConfig(); 418 InspectorHighlightConfig config = affectedNodesHighlightConfig();
467 for (unsigned i = 0; i < elements->length(); ++i) { 419 for (unsigned i = 0; i < elements->length(); ++i) {
468 Element* element = elements->item(i); 420 Element* element = elements->item(i);
469 if (element == m_element) 421 if (element == m_element)
470 continue; 422 continue;
471 423
472 InspectorHighlight highlight(element, config, false); 424 InspectorHighlight highlight(element, config, false);
473 highlights->pushObject(highlight.asJSONObject()); 425 highlights->pushObject(highlight.asJSONObject());
474 } 426 }
475 427
476 object->setArray("nodes", highlights.release()); 428 object->setArray("nodes", highlights.release());
477 return object->toJSONString(); 429 return object->toJSONString();
478 } 430 }
479 431
432 bool LayoutEditor::setCSSPropertyValueInCurrentRule(const String& value)
433 {
434 if (!m_element)
435 return false;
436
437 RefPtrWillBeRawPtr<CSSStyleDeclaration> effectiveDeclaration = m_cssAgent->f indEffectiveDeclaration(m_changingProperty, m_matchedRules.get(), m_element->sty le());
438 bool forceImportant = false;
439
440 if (effectiveDeclaration) {
441 CSSStyleRule* effectiveRule = nullptr;
442 if (effectiveDeclaration->parentRule() && effectiveDeclaration->parentRu le()->type() == CSSRule::STYLE_RULE)
443 effectiveRule = toCSSStyleRule(effectiveDeclaration->parentRule());
444
445 unsigned effectiveRuleIndex = m_matchedRules->length();
446 for (unsigned i = 0; i < m_matchedRules->length(); ++i) {
447 if (m_matchedRules->item(i) == effectiveRule) {
448 effectiveRuleIndex = i;
449 break;
450 }
451 }
452 forceImportant = effectiveDeclaration->getPropertyPriority(getPropertyNa meString(m_changingProperty)) == "important";
453 forceImportant |= effectiveRuleIndex > m_currentRuleIndex;
454 }
455
456 CSSStyleDeclaration* style = currentStyleIsInline() ? m_element->style() : t oCSSStyleRule(m_matchedRules->item(m_currentRuleIndex))->style();
457
458 String errorString;
459 m_cssAgent->setCSSPropertyValue(&errorString, m_element.get(), style, m_chan gingProperty, value, forceImportant);
460 return errorString.isEmpty();
461 }
462
480 } // namespace blink 463 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/inspector/LayoutEditor.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698