Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / base / ui / animation_controller.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7 <link rel="import" href="/base/event_target.html">
8 <link rel="import" href="/base/raf.html">
9 <link rel="import" href="/base/ui/animation.html">
10 <script>
11 'use strict';
12
13 tv.exportTo('tv.ui', function() {
14   /**
15    * Manages execution, queueing and blending of tv.ui.Animations against
16    * a single target.
17    *
18    * Targets must have a cloneAnimationState() method that returns all the
19    * animatable states of that target.
20    *
21    * @constructor
22    * @extends {tv.EventTarget}
23    */
24   function AnimationController() {
25     tv.EventTarget.call(this);
26
27     this.target_ = undefined;
28
29     this.activeAnimation_ = undefined;
30
31     this.tickScheduled_ = false;
32   }
33
34   AnimationController.prototype = {
35     __proto__: tv.EventTarget.prototype,
36
37     get target() {
38       return this.target_;
39     },
40
41     set target(target) {
42       if (this.activeAnimation_)
43         throw new Error('Cannot change target while animation is running.');
44       if (target.cloneAnimationState === undefined ||
45           typeof target.cloneAnimationState !== 'function')
46         throw new Error('target must have a cloneAnimationState function');
47
48       this.target_ = target;
49     },
50
51     get activeAnimation() {
52       return this.activeAnimation_;
53     },
54
55     get hasActiveAnimation() {
56       return !!this.activeAnimation_;
57     },
58
59     queueAnimation: function(animation, opt_now) {
60       if (this.target_ === undefined)
61         throw new Error('Cannot queue animations without a target');
62
63       var now;
64       if (opt_now !== undefined)
65         now = opt_now;
66       else
67         now = window.performance.now();
68
69       if (this.activeAnimation_) {
70         // Must tick the animation before stopping it case its about to stop,
71         // and to update the target with its final sets of edits up to this
72         // point.
73         var done = this.activeAnimation_.tick(now, this.target_);
74         if (done)
75           this.activeAnimation_ = undefined;
76       }
77
78       if (this.activeAnimation_) {
79         if (animation.canTakeOverFor(this.activeAnimation_)) {
80           this.activeAnimation_.didStopEarly(now, this.target_, true);
81           animation.takeOverFor(this.activeAnimation_, now, this.target_);
82         } else {
83           this.activeAnimation_.didStopEarly(now, this.target_, false);
84         }
85       }
86       this.activeAnimation_ = animation;
87       this.activeAnimation_.start(now, this.target_);
88
89       if (this.tickScheduled_)
90         return;
91       this.tickScheduled_ = true;
92       tv.requestAnimationFrame(this.tickActiveAnimation_, this);
93     },
94
95     cancelActiveAnimation: function(opt_now) {
96       if (!this.activeAnimation_)
97         return;
98       var now;
99       if (opt_now !== undefined)
100         now = opt_now;
101       else
102         now = window.performance.now();
103       this.activeAnimation_.didStopEarly(now, this.target_, false);
104       this.activeAnimation_ = undefined;
105     },
106
107     tickActiveAnimation_: function(frameBeginTime) {
108       this.tickScheduled_ = false;
109       if (!this.activeAnimation_)
110         return;
111
112       if (this.target_ === undefined) {
113         this.activeAnimation_.didStopEarly(frameBeginTime, this.target_, false);
114         return;
115       }
116
117       var oldTargetState = this.target_.cloneAnimationState();
118
119       var done = this.activeAnimation_.tick(frameBeginTime, this.target_);
120       if (done)
121         this.activeAnimation_ = undefined;
122
123       if (this.activeAnimation_) {
124         this.tickScheduled_ = true;
125         tv.requestAnimationFrame(this.tickActiveAnimation_, this);
126       }
127
128       if (oldTargetState) {
129         var e = new Event('didtick');
130         e.oldTargetState = oldTargetState;
131         this.dispatchEvent(e, false, false);
132       }
133     }
134   };
135
136   return {
137     AnimationController: AnimationController
138   };
139 });
140 </script>