Bug 1476366 - (Part 1) Instrument Rule and TextProperty models to emit event on change. draft
authorRazvan Caliman <rcaliman@mozilla.com>
Thu, 19 Jul 2018 17:31:38 +0200
changeset 820439 b668f51fbfc6b391a84438634ef932e55a2c8bdc
parent 816856 aff060ad3204234adae2d59b3776207c6687ebfc
child 820440 819da2685fd175f34bbb3fad56a582d7ba628055
push id116828
push userbmo:rcaliman@mozilla.com
push dateThu, 19 Jul 2018 15:42:36 +0000
bugs1476366
milestone63.0a1
Bug 1476366 - (Part 1) Instrument Rule and TextProperty models to emit event on change. MozReview-Commit-ID: LD1sA6QWtTP
devtools/client/inspector/rules/models/rule.js
devtools/client/inspector/rules/models/text-property.js
--- a/devtools/client/inspector/rules/models/rule.js
+++ b/devtools/client/inspector/rules/models/rule.js
@@ -12,16 +12,17 @@ const {ELEMENT_STYLE} = require("devtool
 const TextProperty = require("devtools/client/inspector/rules/models/text-property");
 const {promiseWarn} = require("devtools/client/inspector/shared/utils");
 const {parseNamedDeclarations} = require("devtools/shared/css/parsing-utils");
 const Services = require("Services");
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
+const EventEmitter = require("devtools/shared/event-emitter");
 
 /**
  * Rule is responsible for the following:
  *   Manages a single style declaration or rule.
  *   Applies changes to the properties in a rule.
  *   Maintains a list of TextProperty objects.
  *
  * @param {ElementStyle} elementStyle
@@ -31,16 +32,18 @@ const STYLE_INSPECTOR_L10N = new Localiz
  *          rule: A StyleRuleActor
  *          inherited: An element this rule was inherited from.  If omitted,
  *            the rule applies directly to the current element.
  *          isSystem: Is this a user agent style?
  *          isUnmatched: True if the rule does not match the current selected
  *            element, otherwise, false.
  */
 function Rule(elementStyle, options) {
+  EventEmitter.decorate(this);
+
   this.elementStyle = elementStyle;
   this.domRule = options.rule;
   this.matchedSelectors = options.matchedSelectors || [];
   this.pseudoElement = options.pseudoElement || "";
 
   this.isSystem = options.isSystem;
   this.isUnmatched = options.isUnmatched || false;
   this.inherited = options.inherited || null;
@@ -81,16 +84,20 @@ Rule.prototype = {
         eltText += "#" + this.inherited.id;
       }
       this._inheritedSource =
         STYLE_INSPECTOR_L10N.getFormatStr("rule.inheritedFrom", eltText);
     }
     return this._inheritedSource;
   },
 
+  get isInlineStyle() {
+    return this.domRule.type === ELEMENT_STYLE;
+  },
+
   get keyframesName() {
     if (this._keyframesName) {
       return this._keyframesName;
     }
     this._keyframesName = "";
     if (this.keyframes) {
       this._keyframesName =
         STYLE_INSPECTOR_L10N.getFormatStr("rule.keyframe", this.keyframes.name);
@@ -163,16 +170,21 @@ Rule.prototype = {
 
     this.applyProperties((modifications) => {
       modifications.createProperty(ind, name, value, priority, enabled);
       // Now that the rule has been updated, the server might have given us data
       // that changes the state of the property. Update it now.
       prop.updateEditor();
     });
 
+    const change = {
+      rule: this,
+      add: { property: name, value }
+    };
+    this.emit("track-change", change);
     return prop;
   },
 
   /**
    * Helper function for applyProperties that is called when the actor
    * does not support as-authored styles.  Store disabled properties
    * in the element style's store.
    */
@@ -395,16 +407,21 @@ Rule.prototype = {
   removeProperty: function(property) {
     const index = this.textProps.indexOf(property);
     this.textProps.splice(index, 1);
     // Need to re-apply properties in case removing this TextProperty
     // exposes another one.
     this.applyProperties((modifications) => {
       modifications.removeProperty(index, property.name);
     });
+    const change = {
+      rule: this,
+      remove: { property: property.name, value: property.value }
+    };
+    this.emit("track-change", change);
   },
 
   /**
    * Get the list of TextProperties from the style. Needs
    * to parse the style's authoredText.
    */
   _getTextProperties: function() {
     const textProps = [];
--- a/devtools/client/inspector/rules/models/text-property.js
+++ b/devtools/client/inspector/rules/models/text-property.js
@@ -112,21 +112,34 @@ TextProperty.prototype = {
 
     if (changed) {
       this.updateEditor();
     }
   },
 
   setValue: function(value, priority, force = false) {
     const store = this.rule.elementStyle.store;
+    const isValueUpdated = this.editor && value !== this.editor.committed.value;
 
-    if (this.editor && value !== this.editor.committed.value || force) {
+    if (isValueUpdated || force) {
       store.userProperties.setProperty(this.rule.domRule, this.name, value);
     }
 
+    const change = {
+      rule: this.rule,
+      add: { property: this.name, value },
+      remove: isValueUpdated && this.editor.committed.value
+        ? {
+          property: this.name,
+          value: this.editor.committed.value
+        }
+        : null
+    };
+
+    this.rule.emit("track-change", change);
     this.rule.setPropertyValue(this, value, priority);
     this.updateEditor();
   },
 
   /**
    * Called when the property's value has been updated externally, and
    * the property and editor should update to reflect that value.
    *
@@ -153,16 +166,21 @@ TextProperty.prototype = {
   },
 
   setEnabled: function(value) {
     this.rule.setPropertyEnabled(this, value);
     this.updateEditor();
   },
 
   remove: function() {
+    const change = {
+      rule: this.rule,
+      remove: { property: this.name, value: this.value }
+    };
+    this.rule.emit("track-change", change);
     this.rule.removeProperty(this);
   },
 
   /**
    * Return a string representation of the rule property.
    */
   stringifyProperty: function() {
     // Get the displayed property value