OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 | |
5 /** | 4 /** |
6 * @constructor | 5 * @unrestricted |
7 * @param {!WebInspector.TimelineFrameModel} frameModel | |
8 * @extends {WebInspector.SplitWidget} | |
9 */ | 6 */ |
10 WebInspector.TimelinePaintProfilerView = function(frameModel) | 7 WebInspector.TimelinePaintProfilerView = class extends WebInspector.SplitWidget
{ |
11 { | 8 /** |
12 WebInspector.SplitWidget.call(this, false, false); | 9 * @param {!WebInspector.TimelineFrameModel} frameModel |
13 this.element.classList.add("timeline-paint-profiler-view"); | 10 */ |
| 11 constructor(frameModel) { |
| 12 super(false, false); |
| 13 this.element.classList.add('timeline-paint-profiler-view'); |
14 this.setSidebarSize(60); | 14 this.setSidebarSize(60); |
15 this.setResizable(false); | 15 this.setResizable(false); |
16 | 16 |
17 this._frameModel = frameModel; | 17 this._frameModel = frameModel; |
18 this._logAndImageSplitWidget = new WebInspector.SplitWidget(true, false); | 18 this._logAndImageSplitWidget = new WebInspector.SplitWidget(true, false); |
19 this._logAndImageSplitWidget.element.classList.add("timeline-paint-profiler-
log-split"); | 19 this._logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-
log-split'); |
20 this.setMainWidget(this._logAndImageSplitWidget); | 20 this.setMainWidget(this._logAndImageSplitWidget); |
21 this._imageView = new WebInspector.TimelinePaintImageView(); | 21 this._imageView = new WebInspector.TimelinePaintImageView(); |
22 this._logAndImageSplitWidget.setMainWidget(this._imageView); | 22 this._logAndImageSplitWidget.setMainWidget(this._imageView); |
23 | 23 |
24 this._paintProfilerView = new WebInspector.PaintProfilerView(this._imageView
.showImage.bind(this._imageView)); | 24 this._paintProfilerView = new WebInspector.PaintProfilerView(this._imageView
.showImage.bind(this._imageView)); |
25 this._paintProfilerView.addEventListener(WebInspector.PaintProfilerView.Even
ts.WindowChanged, this._onWindowChanged, this); | 25 this._paintProfilerView.addEventListener( |
| 26 WebInspector.PaintProfilerView.Events.WindowChanged, this._onWindowChang
ed, this); |
26 this.setSidebarWidget(this._paintProfilerView); | 27 this.setSidebarWidget(this._paintProfilerView); |
27 | 28 |
28 this._logTreeView = new WebInspector.PaintProfilerCommandLogView(); | 29 this._logTreeView = new WebInspector.PaintProfilerCommandLogView(); |
29 this._logAndImageSplitWidget.setSidebarWidget(this._logTreeView); | 30 this._logAndImageSplitWidget.setSidebarWidget(this._logTreeView); |
30 }; | 31 } |
31 | 32 |
32 WebInspector.TimelinePaintProfilerView.prototype = { | 33 /** |
33 wasShown: function() | 34 * @override |
34 { | 35 */ |
35 if (this._needsUpdateWhenVisible) { | 36 wasShown() { |
36 this._needsUpdateWhenVisible = false; | 37 if (this._needsUpdateWhenVisible) { |
37 this._update(); | 38 this._needsUpdateWhenVisible = false; |
38 } | 39 this._update(); |
39 }, | 40 } |
| 41 } |
| 42 |
| 43 /** |
| 44 * @param {!WebInspector.PaintProfilerSnapshot} snapshot |
| 45 */ |
| 46 setSnapshot(snapshot) { |
| 47 this._releaseSnapshot(); |
| 48 this._pendingSnapshot = snapshot; |
| 49 this._event = null; |
| 50 this._updateWhenVisible(); |
| 51 } |
| 52 |
| 53 /** |
| 54 * @param {!WebInspector.Target} target |
| 55 * @param {!WebInspector.TracingModel.Event} event |
| 56 * @return {boolean} |
| 57 */ |
| 58 setEvent(target, event) { |
| 59 this._releaseSnapshot(); |
| 60 this._target = target; |
| 61 this._pendingSnapshot = null; |
| 62 this._event = event; |
| 63 |
| 64 this._updateWhenVisible(); |
| 65 if (this._event.name === WebInspector.TimelineModel.RecordType.Paint) |
| 66 return !!event.picture; |
| 67 if (this._event.name === WebInspector.TimelineModel.RecordType.RasterTask) |
| 68 return this._frameModel.hasRasterTile(this._event); |
| 69 return false; |
| 70 } |
| 71 |
| 72 _updateWhenVisible() { |
| 73 if (this.isShowing()) |
| 74 this._update(); |
| 75 else |
| 76 this._needsUpdateWhenVisible = true; |
| 77 } |
| 78 |
| 79 _update() { |
| 80 this._logTreeView.setCommandLog(null, []); |
| 81 this._paintProfilerView.setSnapshotAndLog(null, [], null); |
| 82 |
| 83 var snapshotPromise; |
| 84 if (this._pendingSnapshot) |
| 85 snapshotPromise = Promise.resolve({rect: null, snapshot: this._pendingSnap
shot}); |
| 86 else if (this._event.name === WebInspector.TimelineModel.RecordType.Paint) { |
| 87 snapshotPromise = this._event.picture.objectPromise() |
| 88 .then(data => WebInspector.PaintProfilerSnapshot.loa
d(this._target, data['skp64'])) |
| 89 .then(snapshot => snapshot && {rect: null, snapshot:
snapshot}); |
| 90 } else if (this._event.name === WebInspector.TimelineModel.RecordType.Raster
Task) { |
| 91 snapshotPromise = this._frameModel.rasterTilePromise(this._event); |
| 92 } else { |
| 93 console.assert(false, 'Unexpected event type or no snapshot'); |
| 94 return; |
| 95 } |
| 96 snapshotPromise.then(snapshotWithRect => { |
| 97 this._releaseSnapshot(); |
| 98 if (!snapshotWithRect) { |
| 99 this._imageView.showImage(); |
| 100 return; |
| 101 } |
| 102 var snapshot = snapshotWithRect.snapshot; |
| 103 this._lastLoadedSnapshot = snapshot; |
| 104 this._imageView.setMask(snapshotWithRect.rect); |
| 105 snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, sn
apshotWithRect.rect, log)); |
| 106 }); |
40 | 107 |
41 /** | 108 /** |
42 * @param {!WebInspector.PaintProfilerSnapshot} snapshot | 109 * @param {!WebInspector.PaintProfilerSnapshot} snapshot |
| 110 * @param {?DOMAgent.Rect} clipRect |
| 111 * @param {!Array.<!WebInspector.PaintProfilerLogItem>=} log |
| 112 * @this {WebInspector.TimelinePaintProfilerView} |
43 */ | 113 */ |
44 setSnapshot: function(snapshot) | 114 function onCommandLogDone(snapshot, clipRect, log) { |
45 { | 115 this._logTreeView.setCommandLog(snapshot.target(), log || []); |
46 this._releaseSnapshot(); | 116 this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect); |
47 this._pendingSnapshot = snapshot; | 117 } |
48 this._event = null; | 118 } |
49 this._updateWhenVisible(); | 119 |
50 }, | 120 _releaseSnapshot() { |
51 | 121 if (!this._lastLoadedSnapshot) |
52 /** | 122 return; |
53 * @param {!WebInspector.Target} target | 123 this._lastLoadedSnapshot.release(); |
54 * @param {!WebInspector.TracingModel.Event} event | 124 this._lastLoadedSnapshot = null; |
55 * @return {boolean} | 125 } |
56 */ | 126 |
57 setEvent: function(target, event) | 127 _onWindowChanged() { |
58 { | 128 this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow()); |
59 this._releaseSnapshot(); | 129 } |
60 this._target = target; | |
61 this._pendingSnapshot = null; | |
62 this._event = event; | |
63 | |
64 this._updateWhenVisible(); | |
65 if (this._event.name === WebInspector.TimelineModel.RecordType.Paint) | |
66 return !!event.picture; | |
67 if (this._event.name === WebInspector.TimelineModel.RecordType.RasterTas
k) | |
68 return this._frameModel.hasRasterTile(this._event); | |
69 return false; | |
70 }, | |
71 | |
72 _updateWhenVisible: function() | |
73 { | |
74 if (this.isShowing()) | |
75 this._update(); | |
76 else | |
77 this._needsUpdateWhenVisible = true; | |
78 }, | |
79 | |
80 _update: function() | |
81 { | |
82 this._logTreeView.setCommandLog(null, []); | |
83 this._paintProfilerView.setSnapshotAndLog(null, [], null); | |
84 | |
85 var snapshotPromise; | |
86 if (this._pendingSnapshot) | |
87 snapshotPromise = Promise.resolve({rect: null, snapshot: this._pendi
ngSnapshot}); | |
88 else if (this._event.name === WebInspector.TimelineModel.RecordType.Pain
t) { | |
89 snapshotPromise = this._event.picture.objectPromise() | |
90 .then(data => WebInspector.PaintProfilerSnapshot.load(this._targ
et, data["skp64"])) | |
91 .then(snapshot => snapshot && {rect: null, snapshot: snapshot}); | |
92 } else if (this._event.name === WebInspector.TimelineModel.RecordType.Ra
sterTask) { | |
93 snapshotPromise = this._frameModel.rasterTilePromise(this._event); | |
94 } else { | |
95 console.assert(false, "Unexpected event type or no snapshot"); | |
96 return; | |
97 } | |
98 snapshotPromise.then(snapshotWithRect => { | |
99 this._releaseSnapshot(); | |
100 if (!snapshotWithRect) { | |
101 this._imageView.showImage(); | |
102 return; | |
103 } | |
104 var snapshot = snapshotWithRect.snapshot; | |
105 this._lastLoadedSnapshot = snapshot; | |
106 this._imageView.setMask(snapshotWithRect.rect); | |
107 snapshot.commandLog().then(log => onCommandLogDone.call(this, snapsh
ot, snapshotWithRect.rect, log)); | |
108 }); | |
109 | |
110 /** | |
111 * @param {!WebInspector.PaintProfilerSnapshot} snapshot | |
112 * @param {?DOMAgent.Rect} clipRect | |
113 * @param {!Array.<!WebInspector.PaintProfilerLogItem>=} log | |
114 * @this {WebInspector.TimelinePaintProfilerView} | |
115 */ | |
116 function onCommandLogDone(snapshot, clipRect, log) | |
117 { | |
118 this._logTreeView.setCommandLog(snapshot.target(), log || []); | |
119 this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipR
ect); | |
120 } | |
121 }, | |
122 | |
123 _releaseSnapshot: function() | |
124 { | |
125 if (!this._lastLoadedSnapshot) | |
126 return; | |
127 this._lastLoadedSnapshot.release(); | |
128 this._lastLoadedSnapshot = null; | |
129 }, | |
130 | |
131 _onWindowChanged: function() | |
132 { | |
133 this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow()
); | |
134 }, | |
135 | |
136 __proto__: WebInspector.SplitWidget.prototype | |
137 }; | 130 }; |
138 | 131 |
139 /** | 132 /** |
140 * @constructor | 133 * @unrestricted |
141 * @extends {WebInspector.Widget} | |
142 */ | 134 */ |
143 WebInspector.TimelinePaintImageView = function() | 135 WebInspector.TimelinePaintImageView = class extends WebInspector.Widget { |
144 { | 136 constructor() { |
145 WebInspector.Widget.call(this, true); | 137 super(true); |
146 this.registerRequiredCSS("timeline/timelinePaintProfiler.css"); | 138 this.registerRequiredCSS('timeline/timelinePaintProfiler.css'); |
147 this.contentElement.classList.add("fill", "paint-profiler-image-view"); | 139 this.contentElement.classList.add('fill', 'paint-profiler-image-view'); |
148 this._imageContainer = this.contentElement.createChild("div", "paint-profile
r-image-container"); | 140 this._imageContainer = this.contentElement.createChild('div', 'paint-profile
r-image-container'); |
149 this._imageElement = this._imageContainer.createChild("img"); | 141 this._imageElement = this._imageContainer.createChild('img'); |
150 this._maskElement = this._imageContainer.createChild("div"); | 142 this._maskElement = this._imageContainer.createChild('div'); |
151 this._imageElement.addEventListener("load", this._updateImagePosition.bind(t
his), false); | 143 this._imageElement.addEventListener('load', this._updateImagePosition.bind(t
his), false); |
152 | 144 |
153 this._transformController = new WebInspector.TransformController(this.conten
tElement, true); | 145 this._transformController = new WebInspector.TransformController(this.conten
tElement, true); |
154 this._transformController.addEventListener(WebInspector.TransformController.
Events.TransformChanged, this._updateImagePosition, this); | 146 this._transformController.addEventListener( |
| 147 WebInspector.TransformController.Events.TransformChanged, this._updateIm
agePosition, this); |
| 148 } |
| 149 |
| 150 /** |
| 151 * @override |
| 152 */ |
| 153 onResize() { |
| 154 if (this._imageElement.src) |
| 155 this._updateImagePosition(); |
| 156 } |
| 157 |
| 158 _updateImagePosition() { |
| 159 var width = this._imageElement.naturalWidth; |
| 160 var height = this._imageElement.naturalHeight; |
| 161 var clientWidth = this.contentElement.clientWidth; |
| 162 var clientHeight = this.contentElement.clientHeight; |
| 163 |
| 164 var paddingFraction = 0.1; |
| 165 var paddingX = clientWidth * paddingFraction; |
| 166 var paddingY = clientHeight * paddingFraction; |
| 167 var scaleX = (clientWidth - paddingX) / width; |
| 168 var scaleY = (clientHeight - paddingY) / height; |
| 169 var scale = Math.min(scaleX, scaleY); |
| 170 |
| 171 if (this._maskRectangle) { |
| 172 var style = this._maskElement.style; |
| 173 style.width = width + 'px'; |
| 174 style.height = height + 'px'; |
| 175 style.borderLeftWidth = this._maskRectangle.x + 'px'; |
| 176 style.borderTopWidth = this._maskRectangle.y + 'px'; |
| 177 style.borderRightWidth = (width - this._maskRectangle.x - this._maskRectan
gle.width) + 'px'; |
| 178 style.borderBottomWidth = (height - this._maskRectangle.y - this._maskRect
angle.height) + 'px'; |
| 179 } |
| 180 this._transformController.setScaleConstraints(0.5, 10 / scale); |
| 181 var matrix = new WebKitCSSMatrix() |
| 182 .scale(this._transformController.scale(), this._transformCo
ntroller.scale()) |
| 183 .translate(clientWidth / 2, clientHeight / 2) |
| 184 .scale(scale, scale) |
| 185 .translate(-width / 2, -height / 2); |
| 186 var bounds = WebInspector.Geometry.boundsForTransformedPoints(matrix, [0, 0,
0, width, height, 0]); |
| 187 this._transformController.clampOffsets( |
| 188 paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY -
bounds.maxY, |
| 189 clientHeight - paddingY - bounds.minY); |
| 190 matrix = new WebKitCSSMatrix() |
| 191 .translate(this._transformController.offsetX(), this._transform
Controller.offsetY()) |
| 192 .multiply(matrix); |
| 193 this._imageContainer.style.webkitTransform = matrix.toString(); |
| 194 } |
| 195 |
| 196 /** |
| 197 * @param {string=} imageURL |
| 198 */ |
| 199 showImage(imageURL) { |
| 200 this._imageContainer.classList.toggle('hidden', !imageURL); |
| 201 if (imageURL) |
| 202 this._imageElement.src = imageURL; |
| 203 } |
| 204 |
| 205 /** |
| 206 * @param {?DOMAgent.Rect} maskRectangle |
| 207 */ |
| 208 setMask(maskRectangle) { |
| 209 this._maskRectangle = maskRectangle; |
| 210 this._maskElement.classList.toggle('hidden', !maskRectangle); |
| 211 } |
155 }; | 212 }; |
156 | |
157 WebInspector.TimelinePaintImageView.prototype = { | |
158 onResize: function() | |
159 { | |
160 if (this._imageElement.src) | |
161 this._updateImagePosition(); | |
162 }, | |
163 | |
164 _updateImagePosition: function() | |
165 { | |
166 var width = this._imageElement.naturalWidth; | |
167 var height = this._imageElement.naturalHeight; | |
168 var clientWidth = this.contentElement.clientWidth; | |
169 var clientHeight = this.contentElement.clientHeight; | |
170 | |
171 var paddingFraction = 0.1; | |
172 var paddingX = clientWidth * paddingFraction; | |
173 var paddingY = clientHeight * paddingFraction; | |
174 var scaleX = (clientWidth - paddingX) / width; | |
175 var scaleY = (clientHeight - paddingY) / height; | |
176 var scale = Math.min(scaleX, scaleY); | |
177 | |
178 if (this._maskRectangle) { | |
179 var style = this._maskElement.style; | |
180 style.width = width + "px"; | |
181 style.height = height + "px"; | |
182 style.borderLeftWidth = this._maskRectangle.x + "px"; | |
183 style.borderTopWidth = this._maskRectangle.y + "px"; | |
184 style.borderRightWidth = (width - this._maskRectangle.x - this._mask
Rectangle.width) + "px"; | |
185 style.borderBottomWidth = (height - this._maskRectangle.y - this._ma
skRectangle.height) + "px"; | |
186 } | |
187 this._transformController.setScaleConstraints(0.5, 10 / scale); | |
188 var matrix = new WebKitCSSMatrix() | |
189 .scale(this._transformController.scale(), this._transformController.
scale()) | |
190 .translate(clientWidth / 2, clientHeight / 2) | |
191 .scale(scale, scale) | |
192 .translate(-width / 2, -height / 2); | |
193 var bounds = WebInspector.Geometry.boundsForTransformedPoints(matrix, [0
, 0, 0, width, height, 0]); | |
194 this._transformController.clampOffsets(paddingX - bounds.maxX, clientWid
th - paddingX - bounds.minX, | |
195 paddingY - bounds.maxY, clientHeight - paddingY - bounds.minY); | |
196 matrix = new WebKitCSSMatrix().translate(this._transformController.offse
tX(), this._transformController.offsetY()).multiply(matrix); | |
197 this._imageContainer.style.webkitTransform = matrix.toString(); | |
198 }, | |
199 | |
200 /** | |
201 * @param {string=} imageURL | |
202 */ | |
203 showImage: function(imageURL) | |
204 { | |
205 this._imageContainer.classList.toggle("hidden", !imageURL); | |
206 if (imageURL) | |
207 this._imageElement.src = imageURL; | |
208 }, | |
209 | |
210 /** | |
211 * @param {?DOMAgent.Rect} maskRectangle | |
212 */ | |
213 setMask: function(maskRectangle) | |
214 { | |
215 this._maskRectangle = maskRectangle; | |
216 this._maskElement.classList.toggle("hidden", !maskRectangle); | |
217 }, | |
218 | |
219 __proto__: WebInspector.Widget.prototype | |
220 }; | |
OLD | NEW |