Web Inspector: Graphics: should use the `id` (name) of the animation if it exists
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Jun 2020 01:12:01 +0000 (01:12 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Jun 2020 01:12:01 +0000 (01:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=212618

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/protocol/Animation.json:
 - added an optional `name` property to the `Animation.Animation` type
 - created a new `Animation.nameChanged` event

Source/WebCore:

Test: inspector/animation/lifecycle-css-animation.html:
      inspector/animation/lifecycle-css-transition.html:
      inspector/animation/lifecycle-web-animation.html:
      inspector/animation/nameChanged.html

* animation/WebAnimation.h:
(WebCore::WebAnimation::setId): Deleted.
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::setId): Added.

* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::didChangeWebAnimationName): Added.
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::didChangeWebAnimationNameImpl): Added.

* inspector/agents/InspectorAnimationAgent.h:
* inspector/agents/InspectorAnimationAgent.cpp:
(WebCore::InspectorAnimationAgent::didChangeWebAnimationName): Added.
(WebCore::InspectorAnimationAgent::bindAnimation):

Source/WebInspectorUI:

* UserInterface/Protocol/AnimationObserver.js:
(WI.AnimationObserver.prototype.nameChanged): Added.
* UserInterface/Controllers/AnimationManager.js:
(WI.AnimationManager.prototype.nameChanged): Added.

* UserInterface/Models/Animation.js:
(WI.Animation):
(WI.Animation.fromPayload):
(WI.Animation.prototype.get name): Added.
(WI.Animation.prototype.get cssAnimationName): Added.
(WI.Animation.prototype.get cssTransitionProperty): Added.
(WI.Animation.prototype.get displayName):
(WI.Animation.prototype.nameChanged): Added.

* UserInterface/Views/AnimationContentView.js:
(WI.AnimationContentView.prototype.initialLayout):
(WI.AnimationContentView.prototype.layout):
(WI.AnimationContentView.prototype.attached):
(WI.AnimationContentView.prototype.detached):
(WI.AnimationContentView.prototype._refreshTitle): Added.
(WI.AnimationContentView.prototype._handleNameChanged): Added.
* UserInterface/Views/AnimationContentView.css:
(.content-view.animation):
(.content-view.animation > header > .titles):
(.content-view.animation > header > .titles > .title > code): Added.
Show the `animation-name`/`transition-property`/count in parenthesis after the `id` (only if
it has been specified).
Drive-by: ensure that the `<header>` doesn't overflow.
* UserInterface/Views/AnimationDetailsSidebarPanel.js:
(WI.AnimationDetailsSidebarPanel.prototype.set animation):
(WI.AnimationDetailsSidebarPanel.prototype.initialLayout):
(WI.AnimationDetailsSidebarPanel.prototype._refreshIdentitySection):
(WI.AnimationDetailsSidebarPanel.prototype._handleAnimationNameChanged): Added.
Only show the "Identifier" row if an `id` is actually set. If there is a CSS
`animation-name`/`transition-property`, show it in a separate row.

* Localizations/en.lproj/localizedStrings.js:

LayoutTests:

* inspector/animation/nameChanged.html: Added.
* inspector/animation/nameChanged-expected.txt: Added.

* inspector/animation/resources/lifecycle-utilities.js:
* inspector/animation/lifecycle-css-animation-expected.txt:
* inspector/animation/lifecycle-css-transition-expected.txt:
* inspector/animation/lifecycle-web-animation.html:
* inspector/animation/lifecycle-web-animation-expected.txt:
Print out the name of the animation after it's created.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@262404 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/animation/lifecycle-css-animation-expected.txt
LayoutTests/inspector/animation/lifecycle-css-transition-expected.txt
LayoutTests/inspector/animation/lifecycle-web-animation-expected.txt
LayoutTests/inspector/animation/lifecycle-web-animation.html
LayoutTests/inspector/animation/nameChanged-expected.txt [new file with mode: 0644]
LayoutTests/inspector/animation/nameChanged.html [new file with mode: 0644]
LayoutTests/inspector/animation/resources/lifecycle-utilities.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Animation.json
Source/WebCore/ChangeLog
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/animation/WebAnimation.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp
Source/WebCore/inspector/agents/InspectorAnimationAgent.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Controllers/AnimationManager.js
Source/WebInspectorUI/UserInterface/Models/Animation.js
Source/WebInspectorUI/UserInterface/Protocol/AnimationObserver.js
Source/WebInspectorUI/UserInterface/Views/AnimationContentView.css
Source/WebInspectorUI/UserInterface/Views/AnimationContentView.js
Source/WebInspectorUI/UserInterface/Views/AnimationDetailsSidebarPanel.js

index 1aacca8..35bf472 100644 (file)
@@ -1,3 +1,20 @@
+2020-06-01  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Graphics: should use the `id` (name) of the animation if it exists
+        https://bugs.webkit.org/show_bug.cgi?id=212618
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/animation/nameChanged.html: Added.
+        * inspector/animation/nameChanged-expected.txt: Added.
+
+        * inspector/animation/resources/lifecycle-utilities.js:
+        * inspector/animation/lifecycle-css-animation-expected.txt:
+        * inspector/animation/lifecycle-css-transition-expected.txt:
+        * inspector/animation/lifecycle-web-animation.html:
+        * inspector/animation/lifecycle-web-animation-expected.txt:
+        Print out the name of the animation after it's created.
+
 2020-06-01  Ryan Haddad  <ryanhaddad@apple.com>
 
         [ macOS ] REGRESSION(r262366): webgl/1.0.3/conformance/canvas/buffer-offscreen-test.html & webgl/2.0.0/conformance/canvas/buffer-offscreen-test.html are constant failures
index 90dd2bf..ddb497a 100644 (file)
@@ -4,7 +4,7 @@ Tests for the Animation.animationCreated and Animation.animationDestroyed events
 == Running test suite: Animation.Lifecycle
 -- Running test case: Animation.Lifecycle.CSSAnimation
 PASS: There should not be any animations.
-PASS: Animation created.
+PASS: Animation created 'fade-in'.
 PASS: Animation type should be CSS Animation.
 startDelay: 100
 iterationCount: 2
index fab2bb5..58ed275 100644 (file)
@@ -4,7 +4,7 @@ Tests for the Animation.animationCreated and Animation.animationDestroyed events
 == Running test suite: Animation.Lifecycle
 -- Running test case: Animation.Lifecycle.CSSTransition
 PASS: There should not be any animations.
-PASS: Animation created.
+PASS: Animation created 'opacity'.
 PASS: Animation type should be CSS Transition.
 startDelay: 100
 iterationCount: 1
index 9aa6b8d..04d98af 100644 (file)
@@ -6,7 +6,7 @@ Tests for the Animation.animationCreated and Animation.animationDestroyed events
 PASS: There should not be any animations.
 Creating animation...
 
-PASS: Animation created.
+PASS: Animation created 'web-animation-test'.
   0: animate - [native code]
   1: createAnimation - inspector/animation/resources/lifecycle-utilities.js:7:35
   2: Global Code - [program code]
index f0270a4..9c0687f 100644 (file)
@@ -31,6 +31,7 @@ function test()
                     },
                 ],
                 options: {
+                    id: "web-animation-test",
                     delay: 100,
                     endDelay: 200,
                     duration: 300,
diff --git a/LayoutTests/inspector/animation/nameChanged-expected.txt b/LayoutTests/inspector/animation/nameChanged-expected.txt
new file mode 100644 (file)
index 0000000..fa133b2
--- /dev/null
@@ -0,0 +1,10 @@
+Tests for the Animation.nameChanged event.
+
+
+== Running test suite: Animation.nameChanged
+-- Running test case: Animation.nameChanged.NewString
+PASS: Animation should have the name 'OldName'.
+Changing name...
+
+PASS: Animation should have the name 'NewName'.
+
diff --git a/LayoutTests/inspector/animation/nameChanged.html b/LayoutTests/inspector/animation/nameChanged.html
new file mode 100644 (file)
index 0000000..7f86633
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function load() {
+    window.animation = document.body.animate([], {id: "OldName"});
+
+    runTest();
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Animation.nameChanged");
+
+    suite.addTestCase({
+        name: "Animation.nameChanged.NewString",
+        description: "Should send the new name to the frontend when `Animation.prototype.set id` is called.",
+        async test() {
+            let animations = Array.from(WI.animationManager.animationCollection);
+            InspectorTest.assert(animations.length === 1, "There should only be one animation.");
+
+            let animation = animations[0];
+            if (!animation) {
+                throw `Missing animation.`;
+                return;
+            }
+
+            InspectorTest.assert(animation.animationType === WI.Animation.Type.WebAnimation, "Animation should be a web animation.");
+
+            InspectorTest.expectEqual(animation.displayName, "OldName", "Animation should have the name 'OldName'.");
+
+            InspectorTest.log("Changing name...\n");
+            await Promise.all([
+                animation.awaitEvent(WI.Animation.Event.NameChanged),
+                InspectorTest.evaluateInPage(`window.animation.id = "NewName"`),
+            ]);
+
+            InspectorTest.expectEqual(animation.displayName, "NewName", "Animation should have the name 'NewName'.");
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="load()">
+    <p>Tests for the Animation.nameChanged event.</p>
+</body>
+</html>
index d9c212f..f05ec38 100644 (file)
@@ -48,12 +48,18 @@ TestPage.registerInitializer(() => {
     InspectorTest.AnimationLifecycleUtilities = {};
 
     InspectorTest.AnimationLifecycleUtilities.awaitAnimationCreated = async function(animationType) {
-        let animationCollectionItemAddedEvent = await WI.animationManager.animationCollection.awaitEvent(WI.Collection.Event.ItemAdded);
+        let nameChangedPromise = null;
+        if (animationType === WI.Animation.Type.WebAnimation)
+            nameChangedPromise = WI.Animation.awaitEvent(WI.Animation.Event.NameChanged);
 
-        InspectorTest.pass("Animation created.");
+        let animationCollectionItemAddedEvent = await WI.animationManager.animationCollection.awaitEvent(WI.Collection.Event.ItemAdded);
 
         let animation = animationCollectionItemAddedEvent.data.item;
 
+        await nameChangedPromise;
+
+        InspectorTest.pass(`Animation created '${animation.displayName}'.`);
+
         for (let i = 0; i < animation.backtrace.length; ++i) {
             let callFrame = animation.backtrace[i];
             let traceText = `  ${i}: `;
index aa1f88f..b4ff204 100644 (file)
@@ -1,3 +1,14 @@
+2020-06-01  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Graphics: should use the `id` (name) of the animation if it exists
+        https://bugs.webkit.org/show_bug.cgi?id=212618
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/protocol/Animation.json:
+         - added an optional `name` property to the `Animation.Animation` type
+         - created a new `Animation.nameChanged` event
+
 2020-06-01  Saam Barati  <sbarati@apple.com>
 
         Correct misunderstandings on how ThreadSpecific work
index 22ee882..119e4e6 100644 (file)
@@ -29,6 +29,7 @@
             "type": "object",
             "properties": [
                 { "name": "animationId", "$ref": "AnimationId" },
+                { "name": "name", "type": "string", "optional": true, "description": "Equal to `Animation.prototype.get id`." },
                 { "name": "cssAnimationName", "type": "string", "optional": true, "description": "Equal to the corresponding `animation-name` CSS property. Should not be provided if `transitionProperty` is also provided." },
                 { "name": "cssTransitionProperty", "type": "string", "optional": true, "description": "Equal to the corresponding `transition-property` CSS property. Should not be provided if `animationName` is also provided." },
                 { "name": "effect", "$ref": "Effect", "optional": true },
             ]
         },
         {
+            "name": "nameChanged",
+            "description": "Dispatched whenever `Animation.prototype.set id` is called.",
+            "parameters": [
+                { "name": "animationId", "$ref": "AnimationId" },
+                { "name": "name", "type": "string", "optional": true, "description": "Equal to `Animation.prototype.get id`." }
+            ]
+        },
+        {
             "name": "effectChanged",
             "description": "Dispatched whenever the effect of any animation is changed in any way.",
             "parameters": [
index 65807d2..11a9d58 100644 (file)
@@ -1,3 +1,30 @@
+2020-06-01  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Graphics: should use the `id` (name) of the animation if it exists
+        https://bugs.webkit.org/show_bug.cgi?id=212618
+
+        Reviewed by Timothy Hatcher.
+
+        Test: inspector/animation/lifecycle-css-animation.html:
+              inspector/animation/lifecycle-css-transition.html:
+              inspector/animation/lifecycle-web-animation.html:
+              inspector/animation/nameChanged.html
+
+        * animation/WebAnimation.h:
+        (WebCore::WebAnimation::setId): Deleted.
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::setId): Added.
+
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::didChangeWebAnimationName): Added.
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::didChangeWebAnimationNameImpl): Added.
+
+        * inspector/agents/InspectorAnimationAgent.h:
+        * inspector/agents/InspectorAnimationAgent.cpp:
+        (WebCore::InspectorAnimationAgent::didChangeWebAnimationName): Added.
+        (WebCore::InspectorAnimationAgent::bindAnimation):
+
 2020-06-01  Andres Gonzalez  <andresg_22@apple.com>
 
         [WebAccessibilityObjectWrapper subrole] should check for the nullity of the underlying AXCoreObject before dereferencing.
index 73f969c..d3f7b57 100644 (file)
@@ -144,6 +144,13 @@ void WebAnimation::effectTimingDidChange()
     InspectorInstrumentation::didChangeWebAnimationEffectTiming(*this);
 }
 
+void WebAnimation::setId(const String& id)
+{
+    m_id = id;
+
+    InspectorInstrumentation::didChangeWebAnimationName(*this);
+}
+
 void WebAnimation::setBindingsEffect(RefPtr<AnimationEffect>&& newEffect)
 {
     setEffect(WTFMove(newEffect));
index 52cbcf2..bc35898 100644 (file)
@@ -63,7 +63,7 @@ public:
     virtual bool isCSSTransition() const { return false; }
 
     const String& id() const { return m_id; }
-    void setId(const String& id) { m_id = id; }
+    void setId(const String&);
 
     AnimationEffect* bindingsEffect() const { return effect(); }
     virtual void setBindingsEffect(RefPtr<AnimationEffect>&&);
index aca9328..b0d7664 100644 (file)
@@ -1142,6 +1142,12 @@ void InspectorInstrumentation::willApplyKeyframeEffectImpl(InstrumentingAgents&
         animationAgent->willApplyKeyframeEffect(target, effect, computedTiming);
 }
 
+void InspectorInstrumentation::didChangeWebAnimationNameImpl(InstrumentingAgents& instrumentingAgents, WebAnimation& animation)
+{
+    if (auto* animationAgent = instrumentingAgents.enabledInspectorAnimationAgent())
+        animationAgent->didChangeWebAnimationName(animation);
+}
+
 void InspectorInstrumentation::didSetWebAnimationEffectImpl(InstrumentingAgents& instrumentingAgents, WebAnimation& animation)
 {
     if (auto* animationAgent = instrumentingAgents.enabledInspectorAnimationAgent())
index 1889564..c7b66ba 100644 (file)
@@ -308,6 +308,7 @@ public:
 #endif
 
     static void willApplyKeyframeEffect(Element&, KeyframeEffect&, ComputedEffectTiming);
+    static void didChangeWebAnimationName(WebAnimation&);
     static void didSetWebAnimationEffect(WebAnimation&);
     static void didChangeWebAnimationEffectTiming(WebAnimation&);
     static void didChangeWebAnimationEffectTarget(WebAnimation&);
@@ -514,6 +515,7 @@ private:
 #endif
 
     static void willApplyKeyframeEffectImpl(InstrumentingAgents&, Element&, KeyframeEffect&, ComputedEffectTiming);
+    static void didChangeWebAnimationNameImpl(InstrumentingAgents&, WebAnimation&);
     static void didSetWebAnimationEffectImpl(InstrumentingAgents&, WebAnimation&);
     static void didChangeWebAnimationEffectTimingImpl(InstrumentingAgents&, WebAnimation&);
     static void didChangeWebAnimationEffectTargetImpl(InstrumentingAgents&, WebAnimation&);
@@ -1488,6 +1490,13 @@ inline void InspectorInstrumentation::willApplyKeyframeEffect(Element& target, K
         willApplyKeyframeEffectImpl(*instrumentingAgents, target, effect, computedTiming);
 }
 
+inline void InspectorInstrumentation::didChangeWebAnimationName(WebAnimation& animation)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (auto* instrumentingAgents = instrumentingAgentsForContext(animation.scriptExecutionContext()))
+        didChangeWebAnimationNameImpl(*instrumentingAgents, animation);
+}
+
 inline void InspectorInstrumentation::didSetWebAnimationEffect(WebAnimation& animation)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
index c7f7dee..e1857b8 100644 (file)
@@ -434,6 +434,17 @@ void InspectorAnimationAgent::willApplyKeyframeEffect(Element& target, KeyframeE
     m_frontendDispatcher->trackingUpdate(m_environment.executionStopwatch().elapsedTime().seconds(), WTFMove(event));
 }
 
+void InspectorAnimationAgent::didChangeWebAnimationName(WebAnimation& animation)
+{
+    // The `animationId` may be empty if Animation is tracking but not enabled.
+    auto animationId = findAnimationId(animation);
+    if (animationId.isEmpty())
+        return;
+
+    auto name = animation.id();
+    m_frontendDispatcher->nameChanged(animationId, !name.isEmpty() ? &name : nullptr);
+}
+
 void InspectorAnimationAgent::didSetWebAnimationEffect(WebAnimation& animation)
 {
     if (is<DeclarativeAnimation>(animation))
@@ -531,6 +542,10 @@ void InspectorAnimationAgent::bindAnimation(WebAnimation& animation, bool captur
         .setAnimationId(animationId)
         .release();
 
+    auto name = animation.id();
+    if (!name.isEmpty())
+        animationPayload->setName(name);
+
     if (is<CSSAnimation>(animation))
         animationPayload->setCssAnimationName(downcast<CSSAnimation>(animation).animationName());
     else if (is<CSSTransition>(animation))
index d266d7e..8b51162 100644 (file)
@@ -67,6 +67,7 @@ public:
 
     // InspectorInstrumentation
     void willApplyKeyframeEffect(Element&, KeyframeEffect&, ComputedEffectTiming);
+    void didChangeWebAnimationName(WebAnimation&);
     void didSetWebAnimationEffect(WebAnimation&);
     void didChangeWebAnimationEffectTiming(WebAnimation&);
     void didChangeWebAnimationEffectTarget(WebAnimation&);
index 0920ae9..73d5f88 100644 (file)
@@ -1,3 +1,49 @@
+2020-06-01  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Graphics: should use the `id` (name) of the animation if it exists
+        https://bugs.webkit.org/show_bug.cgi?id=212618
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Protocol/AnimationObserver.js:
+        (WI.AnimationObserver.prototype.nameChanged): Added.
+        * UserInterface/Controllers/AnimationManager.js:
+        (WI.AnimationManager.prototype.nameChanged): Added.
+
+        * UserInterface/Models/Animation.js:
+        (WI.Animation):
+        (WI.Animation.fromPayload):
+        (WI.Animation.prototype.get name): Added.
+        (WI.Animation.prototype.get cssAnimationName): Added.
+        (WI.Animation.prototype.get cssTransitionProperty): Added.
+        (WI.Animation.prototype.get displayName):
+        (WI.Animation.prototype.nameChanged): Added.
+
+        * UserInterface/Views/AnimationContentView.js:
+        (WI.AnimationContentView.prototype.initialLayout):
+        (WI.AnimationContentView.prototype.layout):
+        (WI.AnimationContentView.prototype.attached):
+        (WI.AnimationContentView.prototype.detached):
+        (WI.AnimationContentView.prototype._refreshTitle): Added.
+        (WI.AnimationContentView.prototype._handleNameChanged): Added.
+        * UserInterface/Views/AnimationContentView.css:
+        (.content-view.animation):
+        (.content-view.animation > header > .titles):
+        (.content-view.animation > header > .titles > .title > code): Added.
+        Show the `animation-name`/`transition-property`/count in parenthesis after the `id` (only if
+        it has been specified).
+        Drive-by: ensure that the `<header>` doesn't overflow.
+
+        * UserInterface/Views/AnimationDetailsSidebarPanel.js:
+        (WI.AnimationDetailsSidebarPanel.prototype.set animation):
+        (WI.AnimationDetailsSidebarPanel.prototype.initialLayout):
+        (WI.AnimationDetailsSidebarPanel.prototype._refreshIdentitySection):
+        (WI.AnimationDetailsSidebarPanel.prototype._handleAnimationNameChanged): Added.
+        Only show the "Identifier" row if an `id` is actually set. If there is a CSS
+        `animation-name`/`transition-property`, show it in a separate row.
+
+        * Localizations/en.lproj/localizedStrings.js:
+
 2020-06-01  Nikita Vasilyev  <nvasilyev@apple.com>
 
         Web Inspector: Timelines: Edit button has wrong outline
index 6642f32..1cf3ea7 100644 (file)
@@ -70,6 +70,7 @@ localizedStrings["%s interval"] = "%s interval";
 localizedStrings["%s total"] = "%s total";
 localizedStrings["%s transferred"] = "%s transferred";
 localizedStrings["%s:"] = "%s:";
+localizedStrings["(%s)"] = "(%s)";
 localizedStrings["(Action %s)"] = "(Action %s)";
 localizedStrings["(Disk)"] = "(Disk)";
 localizedStrings["(Index)"] = "(Index)";
@@ -661,6 +662,7 @@ localizedStrings["IP"] = "IP";
 localizedStrings["IP Address"] = "IP Address";
 localizedStrings["ITML Context"] = "ITML Context";
 localizedStrings["ITP Debug Mode"] = "ITP Debug Mode";
+localizedStrings["Identifier"] = "Identifier";
 localizedStrings["Identity"] = "Identity";
 localizedStrings["Idle"] = "Idle";
 localizedStrings["If the URL of any script matches one of the regular expression patterns below, any pauses that would have happened in that script will be deferred until execution has continued to outside of that script."] = "If the URL of any script matches one of the regular expression patterns below, any pauses that would have happened in that script will be deferred until execution has continued to outside of that script.";
@@ -943,6 +945,7 @@ localizedStrings["Probes"] = "Probes";
 localizedStrings["Processing Instruction"] = "Processing Instruction";
 localizedStrings["Program %d"] = "Program %d";
 localizedStrings["Properties"] = "Properties";
+localizedStrings["Property"] = "Property";
 localizedStrings["Protocol"] = "Protocol";
 localizedStrings["Pseudo-Element"] = "Pseudo-Element";
 localizedStrings["Query Parameters"] = "Query Parameters";
index ffb412c..82a0a42 100644 (file)
@@ -107,6 +107,16 @@ WI.AnimationManager = class AnimationManager
         this._animationIdMap.set(animation.animationId, animation);
     }
 
+    nameChanged(animationId, name)
+    {
+        let animation = this._animationIdMap.get(animationId);
+        console.assert(animation);
+        if (!animation)
+            return;
+
+        animation.nameChanged(name);
+    }
+
     effectChanged(animationId, effect)
     {
         let animation = this._animationIdMap.get(animationId);
index 2365de5..156e3ed 100644 (file)
@@ -25,7 +25,7 @@
 
 WI.Animation = class Animation extends WI.Object
 {
-    constructor(animationId, {cssAnimationName, cssTransitionProperty, effect, backtrace} = {})
+    constructor(animationId, {name, cssAnimationName, cssTransitionProperty, effect, backtrace} = {})
     {
         super();
 
@@ -34,6 +34,7 @@ WI.Animation = class Animation extends WI.Object
 
         this._animationId = animationId;
 
+        this._name = name || null;
         this._cssAnimationName = cssAnimationName || null;
         this._cssTransitionProperty = cssTransitionProperty || null;
         this._updateEffect(effect);
@@ -48,6 +49,7 @@ WI.Animation = class Animation extends WI.Object
     static fromPayload(payload)
     {
         return new WI.Animation(payload.animationId, {
+            name: payload.name,
             cssAnimationName: payload.cssAnimationName,
             cssTransitionProperty: payload.cssTransitionProperty,
             effect: payload.effect,
@@ -114,6 +116,9 @@ WI.Animation = class Animation extends WI.Object
     // Public
 
     get animationId() { return this._animationId; }
+    get name() { return this._name; }
+    get cssAnimationName() { return this._cssAnimationName; }
+    get cssTransitionProperty() { return this._cssTransitionProperty; }
     get backtrace() { return this._backtrace; }
 
     get animationType()
@@ -172,6 +177,9 @@ WI.Animation = class Animation extends WI.Object
 
     get displayName()
     {
+        if (this._name)
+            return this._name;
+
         if (this._cssAnimationName)
             return this._cssAnimationName;
 
@@ -212,6 +220,13 @@ WI.Animation = class Animation extends WI.Object
 
     // AnimationManager
 
+    nameChanged(name)
+    {
+        this._name = name || null;
+
+        this.dispatchEventToListeners(WI.Animation.Event.NameChanged);
+    }
+
     effectChanged(effect)
     {
         this._updateEffect(effect);
@@ -271,6 +286,7 @@ WI.Animation.FillMode = {
 };
 
 WI.Animation.Event = {
+    NameChanged: "animation-name-changed",
     EffectChanged: "animation-effect-changed",
     TargetChanged: "animation-target-changed",
 };
index 7e56e8b..00823c9 100644 (file)
@@ -32,6 +32,11 @@ WI.AnimationObserver = class AnimationObserver extends InspectorBackend.Dispatch
         WI.animationManager.animationCreated(animation);
     }
 
+    nameChanged(animationId, name)
+    {
+        WI.animationManager.nameChanged(animationId, name);
+    }
+
     effectChanged(animationId, effect)
     {
         WI.animationManager.effectChanged(animationId, effect);
index 7c59904..6b68178 100644 (file)
@@ -25,7 +25,7 @@
 
 .content-view.animation {
     position: relative;
-    width: 100%;
+    width: calc(100% - 8px);
     margin: 4px;
     background-color: var(--background-color-content);
     border: 1px solid var(--border-color);
@@ -44,6 +44,8 @@
 }
 
 .content-view.animation > header > .titles {
+    overflow: hidden;
+    text-overflow: ellipsis;
     white-space: nowrap;
 }
 
     color: var(--text-color-gray-dark);
 }
 
+.content-view.animation > header > .titles > .title > code {
+    font-family: Menlo, monospace;
+    font-size: 11px;
+}
+
 .content-view.animation > header > .titles > .subtitle {
     color: var(--text-color-gray-medium);
 }
index 49d6067..d595d0a 100644 (file)
@@ -62,9 +62,8 @@ WI.AnimationContentView = class AnimationContentView extends WI.ContentView
         let titlesContainer = headerElement.appendChild(document.createElement("div"));
         titlesContainer.className = "titles";
 
-        let titleElement = titlesContainer.appendChild(document.createElement("span"));
-        titleElement.className = "title";
-        titleElement.textContent = this.representedObject.displayName;
+        this._titleElement = titlesContainer.appendChild(document.createElement("span"));
+        this._titleElement.className = "title";
 
         this._subtitleElement = titlesContainer.appendChild(document.createElement("span"));
         this._subtitleElement.className = "subtitle";
@@ -87,6 +86,7 @@ WI.AnimationContentView = class AnimationContentView extends WI.ContentView
     {
         super.layout();
 
+        this._refreshTitle();
         this._refreshSubtitle();
         this._refreshPreview();
     }
@@ -102,6 +102,7 @@ WI.AnimationContentView = class AnimationContentView extends WI.ContentView
     {
         super.attached();
 
+        this.representedObject.addEventListener(WI.Animation.Event.NameChanged, this._handleNameChanged, this);
         this.representedObject.addEventListener(WI.Animation.Event.EffectChanged, this._handleEffectChanged, this);
         this.representedObject.addEventListener(WI.Animation.Event.TargetChanged, this._handleTargetChanged, this);
     }
@@ -110,12 +111,55 @@ WI.AnimationContentView = class AnimationContentView extends WI.ContentView
     {
         this.representedObject.removeEventListener(WI.Animation.Event.TargetChanged, this._handleTargetChanged, this);
         this.representedObject.removeEventListener(WI.Animation.Event.EffectChanged, this._handleEffectChanged, this);
+        this.representedObject.removeEventListener(WI.Animation.Event.NameChanged, this._handleNameChanged, this);
 
         super.detached();
     }
 
     // Private
 
+    _refreshTitle()
+    {
+        this._titleElement.removeChildren();
+
+        let displayName = this.representedObject.displayName;
+
+        let showIdentifierIfDifferent = (cssName) => {
+            let formatString = "";
+            let substitutions = [];
+
+            if (cssName === displayName)
+                formatString = WI.UIString("(%s)");
+            else {
+                formatString = WI.UIString("%s (%s)");
+                substitutions.push(displayName);
+            }
+
+            let cssNameWrapper = document.createElement("code");
+            cssNameWrapper.textContent = cssName;
+            substitutions.push(cssNameWrapper);
+
+            String.format(formatString, substitutions, String.standardFormatters, this._titleElement, function(a, b) {
+                a.append(b);
+                return a;
+            });
+        };
+
+        switch (this.representedObject.animationType) {
+        case WI.Animation.Type.WebAnimation:
+            this._titleElement.textContent = this.representedObject.name || WI.UIString("(%s)").format(displayName);
+            break;
+
+        case WI.Animation.Type.CSSAnimation:
+            showIdentifierIfDifferent(this.representedObject.cssAnimationName);
+            break;
+
+        case WI.Animation.Type.CSSTransition:
+            showIdentifierIfDifferent(this.representedObject.cssTransitionProperty);
+            break;
+        }
+    }
+
     _refreshSubtitle()
     {
         this.representedObject.requestEffectTarget((domNode) => {
@@ -271,6 +315,14 @@ WI.AnimationContentView = class AnimationContentView extends WI.ContentView
         }
     }
 
+    _handleNameChanged(event)
+    {
+        if (!this.didInitialLayout)
+            return;
+
+        this._refreshTitle();
+    }
+
     _handleEffectChanged(event)
     {
         this._refreshPreview();
index 0d5bb28..5f424f9 100644 (file)
@@ -59,11 +59,13 @@ WI.AnimationDetailsSidebarPanel = class AnimationDetailsSidebarPanel extends WI.
         if (this._animation) {
             this._animation.removeEventListener(WI.Animation.Event.TargetChanged, this._handleAnimationTargetChanged, this);
             this._animation.removeEventListener(WI.Animation.Event.EffectChanged, this._handleAnimationEffectChanged, this);
+            this._animation.removeEventListener(WI.Animation.Event.NameChanged, this._handleAnimationNameChanged, this);
         }
 
         this._animation = animation || null;
 
         if (this._animation) {
+            this._animation.addEventListener(WI.Animation.Event.NameChanged, this._handleAnimationNameChanged, this);
             this._animation.addEventListener(WI.Animation.Event.EffectChanged, this._handleAnimationEffectChanged, this);
             this._animation.addEventListener(WI.Animation.Event.TargetChanged, this._handleAnimationTargetChanged, this);
         }
@@ -77,12 +79,14 @@ WI.AnimationDetailsSidebarPanel = class AnimationDetailsSidebarPanel extends WI.
     {
         super.initialLayout();
 
-        this._nameRow = new WI.DetailsSectionSimpleRow(WI.UIString("Name"));
+        this._idRow = new WI.DetailsSectionSimpleRow(WI.UIString("Identifier"));
         this._typeRow = new WI.DetailsSectionSimpleRow(WI.UIString("Type"));
+        this._cssAnimationNameRow = new WI.DetailsSectionSimpleRow(WI.UIString("Name"));
+        this._cssTransitionPropertyRow = new WI.DetailsSectionSimpleRow(WI.UIString("Property"));
         this._targetRow = new WI.DetailsSectionSimpleRow(WI.UIString("Target", "Web Animation Target Label", "Label for the current DOM node target of a web animation"));
 
         const identitySectionTitle = WI.UIString("Identity", "Web Animation Identity Title", "Section title for information about a web animation");
-        let identitySection = new WI.DetailsSection("animation-identity", identitySectionTitle, [new WI.DetailsSectionGroup([this._nameRow, this._typeRow, this._targetRow])]);
+        let identitySection = new WI.DetailsSection("animation-identity", identitySectionTitle, [new WI.DetailsSectionGroup([this._idRow, this._typeRow, this._cssAnimationNameRow, this._cssTransitionPropertyRow, this._targetRow])]);
         this.contentView.element.appendChild(identitySection.element);
 
         this._iterationCountRow = new WI.DetailsSectionSimpleRow(WI.UIString("Iterations", "Web Animation Iteration Count Label", "Label for the number of iterations of a web animation"));
@@ -150,8 +154,29 @@ WI.AnimationDetailsSidebarPanel = class AnimationDetailsSidebarPanel extends WI.
 
     _refreshIdentitySection()
     {
-        this._nameRow.value = this._animation.displayName;
-        this._typeRow.value = WI.Animation.displayNameForAnimationType(this._animation.animationType);
+        let animationType = this._animation.animationType;
+        let displayName = this._animation.displayName;
+        let cssAnimationName = this._animation.cssAnimationName;
+        let cssTransitionProperty = this._animation.cssTransitionProperty;
+
+        switch (animationType) {
+        case WI.Animation.Type.WebAnimation:
+            this._idRow.value = this._animation.name;
+            break;
+
+        case WI.Animation.Type.CSSAnimation:
+            this._idRow.value = cssAnimationName !== displayName ? displayName : null;
+            break;
+
+        case WI.Animation.Type.CSSTransition:
+            this._idRow.value = cssTransitionProperty !== displayName ? displayName : null;
+            break;
+        }
+
+        this._typeRow.value = WI.Animation.displayNameForAnimationType(animationType);
+
+        this._cssAnimationNameRow.value = cssAnimationName;
+        this._cssTransitionPropertyRow.value = cssTransitionProperty;
 
         this._targetRow.value = null;
         this._animation.requestEffectTarget((domNode) => {
@@ -248,6 +273,11 @@ WI.AnimationDetailsSidebarPanel = class AnimationDetailsSidebarPanel extends WI.
         this._backtraceSection.element.hidden = !callFrames.length;
     }
 
+    _handleAnimationNameChanged(event)
+    {
+        this._refreshIdentitySection();
+    }
+
     _handleAnimationEffectChanged(event)
     {
         this._refreshEffectSection();