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

Side by Side Diff: Source/devtools/front_end/components_lazy/FilmStripView.js

Issue 1183483011: DevTools: Support popover on timeline overview. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 | Annotate | Revision Log
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 /** 5 /**
6 * @constructor 6 * @constructor
7 * @extends {WebInspector.HBox} 7 * @extends {WebInspector.HBox}
8 */ 8 */
9 WebInspector.FilmStripView = function() 9 WebInspector.FilmStripView = function()
10 { 10 {
11 WebInspector.HBox.call(this, true); 11 WebInspector.HBox.call(this, true);
12 this.registerRequiredCSS("components_lazy/filmStripView.css"); 12 this.registerRequiredCSS("components_lazy/filmStripView.css");
13 this.contentElement.classList.add("film-strip-view"); 13 this.contentElement.classList.add("film-strip-view");
14 this._mode = WebInspector.FilmStripView.Modes.TimeBased; 14 this._framesContainer = this.contentElement.createChild("div", "frames-conta iner");
15 this.reset(); 15 this.reset();
16 this.setMode(WebInspector.FilmStripView.Modes.TimeBased);
16 } 17 }
17 18
18 WebInspector.FilmStripView.Events = { 19 WebInspector.FilmStripView.Events = {
19 FrameSelected: "FrameSelected", 20 FrameSelected: "FrameSelected",
20 FrameEnter: "FrameEnter", 21 FrameEnter: "FrameEnter",
21 FrameExit: "FrameExit", 22 FrameExit: "FrameExit",
22 } 23 }
23 24
24 WebInspector.FilmStripView.Modes = { 25 WebInspector.FilmStripView.Modes = {
25 TimeBased: "TimeBased", 26 TimeBased: "TimeBased",
26 FrameBased: "FrameBased" 27 FrameBased: "FrameBased"
27 } 28 }
28 29
29 WebInspector.FilmStripView.prototype = { 30 WebInspector.FilmStripView.prototype = {
30 /** 31 /**
31 * @param {string} mode 32 * @param {string} mode
32 */ 33 */
33 setMode: function(mode) 34 setMode: function(mode)
34 { 35 {
35 this._mode = mode; 36 this._mode = mode;
37 this.contentElement.classList.toggle("time-based", mode === WebInspector .FilmStripView.Modes.TimeBased);
36 this.update(); 38 this.update();
37 }, 39 },
38 40
39 /** 41 /**
40 * @param {!WebInspector.FilmStripModel} filmStripModel 42 * @param {!WebInspector.FilmStripModel} filmStripModel
41 * @param {number} zeroTime 43 * @param {number} zeroTime
42 * @param {number} spanTime 44 * @param {number} spanTime
43 */ 45 */
44 setModel: function(filmStripModel, zeroTime, spanTime) 46 setModel: function(filmStripModel, zeroTime, spanTime)
45 { 47 {
46 this._model = filmStripModel; 48 this._model = filmStripModel;
47 this._zeroTime = zeroTime; 49 this._zeroTime = zeroTime;
48 this._spanTime = spanTime; 50 this._spanTime = spanTime;
49 var frames = filmStripModel.frames(); 51 var frames = filmStripModel.frames();
50 if (!frames.length) { 52 if (!frames.length) {
51 this.reset(); 53 this.reset();
52 return; 54 return;
53 } 55 }
54 this.update(); 56 this.update();
55 }, 57 },
56 58
57 update: function() 59 /**
60 * @param {number} index
61 * @return {!Element}
62 */
63 frameElementByIndex: function(index)
58 { 64 {
59 if (!this._model) 65 var element = this._elementsCache[index];
60 return; 66 if (!element) {
61 var frames = this._model.frames(); 67 var frame = this._model.frames()[index];
caseq 2015/06/16 14:14:49 Is this method guaranteed to always be called afte
alph 2015/06/17 09:17:08 Yes. I can cover it with assert if you want.
62 if (!frames.length)
63 return;
64 this.contentElement.removeChildren();
65 this._label.remove();
66 var zeroTime = this._zeroTime;
67
68 /**
69 * @param {!WebInspector.FilmStripModel.Frame} frame
70 * @param {boolean=} skipTimeLabel
71 * @return {!Element}
72 * @this {WebInspector.FilmStripView}
73 */
74 function createElementForFrame(frame, skipTimeLabel)
75 {
76 var time = frame.timestamp; 68 var time = frame.timestamp;
77 var element = createElementWithClass("div", "frame"); 69 element = createElementWithClass("div", "frame");
78 element.createChild("div", "thumbnail").createChild("img").src = "da ta:image/jpg;base64," + frame.imageData; 70 element.createChild("div", "thumbnail").createChild("img").src = "da ta:image/jpg;base64," + frame.imageData;
79 if (!skipTimeLabel) 71 element.createChild("div", "time").textContent = Number.millisToStri ng(time - this._zeroTime);
80 element.createChild("div", "time").textContent = Number.millisTo String(time - zeroTime);
81 element.addEventListener("mousedown", this._onMouseEvent.bind(this, WebInspector.FilmStripView.Events.FrameSelected, time), false); 72 element.addEventListener("mousedown", this._onMouseEvent.bind(this, WebInspector.FilmStripView.Events.FrameSelected, time), false);
82 element.addEventListener("mouseenter", this._onMouseEvent.bind(this, WebInspector.FilmStripView.Events.FrameEnter, time), false); 73 element.addEventListener("mouseenter", this._onMouseEvent.bind(this, WebInspector.FilmStripView.Events.FrameEnter, time), false);
83 element.addEventListener("mouseout", this._onMouseEvent.bind(this, W ebInspector.FilmStripView.Events.FrameExit, time), false); 74 element.addEventListener("mouseout", this._onMouseEvent.bind(this, W ebInspector.FilmStripView.Events.FrameExit, time), false);
84 element.addEventListener("dblclick", this._onDoubleClick.bind(this, frame), false); 75 element.addEventListener("dblclick", this._onDoubleClick.bind(this, frame), false);
85 this.contentElement.appendChild(element); 76 this._elementsCache[index] = element;
86 return element;
87 } 77 }
78 return element;
79 },
88 80
89 if (this._mode === WebInspector.FilmStripView.Modes.FrameBased) { 81 /**
90 for (var frame of frames) 82 * @param {number} time
91 createElementForFrame.call(this, frame); 83 * @return {number}
92 return; 84 */
93 } 85 frameIndexByTime: function(time)
94 86 {
95 /**
96 * @return {!Element}
97 * @this {WebInspector.FilmStripView}
98 */
99 function createEmptyElement()
100 {
101 var element = createElementWithClass("div", "frame");
102 this.contentElement.appendChild(element);
103 return element;
104 }
105
106 /** 87 /**
107 * @param {number} time 88 * @param {number} time
108 * @param {!WebInspector.FilmStripModel.Frame} frame 89 * @param {!WebInspector.FilmStripModel.Frame} frame
109 * @return {number} 90 * @return {number}
110 */ 91 */
111 function comparator(time, frame) 92 function comparator(time, frame)
112 { 93 {
113 return time - frame.timestamp; 94 return time - frame.timestamp;
114 } 95 }
96 // Using the first frame to fill the interval between recording start
97 // and a moment the frame is taken.
98 return Math.max(this._model.frames().upperBound(time, comparator) - 1, 0 );
caseq 2015/06/16 14:14:49 ditto.
alph 2015/06/17 09:17:08 ditto.
99 },
115 100
116 var width = this.contentElement.clientWidth; 101 update: function()
102 {
103 if (!this._model)
104 return;
105 var frames = this._model.frames();
106 if (!frames.length)
107 return;
108 this._framesContainer.removeChildren();
109 this._label.remove();
caseq 2015/06/16 14:14:49 nit: please remove label into something more descr
alph 2015/06/17 09:17:08 I actually didn't introduce this name, but ok rena
110
111 if (this._mode === WebInspector.FilmStripView.Modes.FrameBased) {
112 for (var i = 0; i < frames.length; ++i)
113 this._framesContainer.appendChild(this.frameElementByIndex(i).cl oneNode(true));
caseq 2015/06/16 14:14:49 So what's the purpose of the cache if we're clonin
alph 2015/06/17 09:17:08 Popover uses cached versions directly.
114 return;
115 }
116
117 var width = this._framesContainer.clientWidth;
117 var scale = this._spanTime / width; 118 var scale = this._spanTime / width;
118 119 var element0 = this.frameElementByIndex(0); // Calculate frame width ba sing on the first frame.
119 // Calculate frame width basing on the first frame. 120 var frameWidth = Math.ceil(WebInspector.measurePreferredSize(element0, t his.contentElement).width);
120 var tempElement = createElementWithClass("div", "frame");
121 tempElement.createChild("div", "thumbnail").createChild("img").src = "da ta:image/jpg;base64," + frames[0].imageData;
122 var frameWidth = Math.ceil(WebInspector.measurePreferredSize(tempElement , this.contentElement).width);
123 if (!frameWidth) 121 if (!frameWidth)
124 return; 122 return;
125 123
126 for (var pos = frameWidth; pos < width; pos += frameWidth) { 124 for (var pos = frameWidth; pos < width; pos += frameWidth) {
127 var time = pos * scale + zeroTime; 125 var time = pos * scale + this._zeroTime;
128 var index = frames.upperBound(time, comparator) - 1; 126 var index = this.frameIndexByTime(time);
129 var element = index >= 0 ? createElementForFrame.call(this, frames[i ndex], true) : createEmptyElement.call(this); 127 var element = this._framesContainer.appendChild(this.frameElementByI ndex(index).cloneNode(true));
caseq 2015/06/16 14:14:49 ditto.
alph 2015/06/17 09:17:08 ditto.
130 element.style.width = frameWidth + "px"; 128 element.style.width = frameWidth + "px";
131 } 129 }
132 }, 130 },
133 131
134 /** 132 /**
135 * @override 133 * @override
136 */ 134 */
137 onResize: function() 135 onResize: function()
138 { 136 {
139 if (this._mode === WebInspector.FilmStripView.Modes.FrameBased) 137 if (this._mode === WebInspector.FilmStripView.Modes.FrameBased)
(...skipping 14 matching lines...) Expand all
154 * @param {!WebInspector.FilmStripModel.Frame} filmStripFrame 152 * @param {!WebInspector.FilmStripModel.Frame} filmStripFrame
155 */ 153 */
156 _onDoubleClick: function(filmStripFrame) 154 _onDoubleClick: function(filmStripFrame)
157 { 155 {
158 WebInspector.Dialog.show(null, new WebInspector.FilmStripView.DialogDele gate(filmStripFrame, this._zeroTime)); 156 WebInspector.Dialog.show(null, new WebInspector.FilmStripView.DialogDele gate(filmStripFrame, this._zeroTime));
159 }, 157 },
160 158
161 reset: function() 159 reset: function()
162 { 160 {
163 this._zeroTime = 0; 161 this._zeroTime = 0;
164 this.contentElement.removeChildren(); 162 this._elementsCache = [];
165 this._label = this.contentElement.createChild("div", "label"); 163 this._framesContainer.removeChildren();
164 this._label = this._framesContainer.createChild("div", "label");
166 this._label.textContent = WebInspector.UIString("No frames recorded. Rel oad page to start recording."); 165 this._label.textContent = WebInspector.UIString("No frames recorded. Rel oad page to start recording.");
167 }, 166 },
168 167
169 setRecording: function() 168 setRecording: function()
170 { 169 {
171 this.reset(); 170 this.reset();
172 this._label.textContent = WebInspector.UIString("Recording frames..."); 171 this._label.textContent = WebInspector.UIString("Recording frames...");
173 }, 172 },
174 173
175 setFetching: function() 174 setFetching: function()
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 278
280 _render: function() 279 _render: function()
281 { 280 {
282 var frame = this._frames[this._index]; 281 var frame = this._frames[this._index];
283 this._imageElement.src = "data:image/jpg;base64," + frame.imageData; 282 this._imageElement.src = "data:image/jpg;base64," + frame.imageData;
284 this._timeLabel.textContent = Number.millisToString(frame.timestamp - th is._zeroTime); 283 this._timeLabel.textContent = Number.millisToString(frame.timestamp - th is._zeroTime);
285 }, 284 },
286 285
287 __proto__: WebInspector.DialogDelegate.prototype 286 __proto__: WebInspector.DialogDelegate.prototype
288 } 287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698