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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
13 * distribution. 13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its 14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from 15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission. 16 * this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30
31 /** 30 /**
32 * @constructor
33 * @extends {WebInspector.VBox}
34 * @implements {WebInspector.DOMNodeHighlighter} 31 * @implements {WebInspector.DOMNodeHighlighter}
35 * @param {!WebInspector.Target} target 32 * @unrestricted
36 * @param {!WebInspector.ResourceTreeModel} resourceTreeModel
37 */ 33 */
38 WebInspector.ScreencastView = function(target, resourceTreeModel) 34 WebInspector.ScreencastView = class extends WebInspector.VBox {
39 { 35 /**
40 WebInspector.VBox.call(this); 36 * @param {!WebInspector.Target} target
37 * @param {!WebInspector.ResourceTreeModel} resourceTreeModel
38 */
39 constructor(target, resourceTreeModel) {
40 super();
41 this._target = target; 41 this._target = target;
42 this._domModel = WebInspector.DOMModel.fromTarget(target); 42 this._domModel = WebInspector.DOMModel.fromTarget(target);
43 this._resourceTreeModel = resourceTreeModel; 43 this._resourceTreeModel = resourceTreeModel;
44 44
45 this.setMinimumSize(150, 150); 45 this.setMinimumSize(150, 150);
46 this.registerRequiredCSS("screencast/screencastView.css"); 46 this.registerRequiredCSS('screencast/screencastView.css');
47 }; 47 }
48 48
49 WebInspector.ScreencastView._bordersSize = 44; 49 initialize() {
50 50 this.element.classList.add('screencast');
51 WebInspector.ScreencastView._navBarHeight = 29; 51
52 52 this._createNavigationBar();
53 WebInspector.ScreencastView._HttpRegex = /^http:\/\/(.+)/; 53
54 54 this._viewportElement = this.element.createChild('div', 'screencast-viewport hidden');
55 WebInspector.ScreencastView._SchemeRegex = /^(https?|about|chrome):/; 55 this._canvasContainerElement = this._viewportElement.createChild('div', 'scr eencast-canvas-container');
56 56 this._glassPaneElement = this._canvasContainerElement.createChild('div', 'sc reencast-glasspane fill hidden');
57 WebInspector.ScreencastView.prototype = { 57
58 initialize: function() 58 this._canvasElement = this._canvasContainerElement.createChild('canvas');
59 { 59 this._canvasElement.tabIndex = 1;
60 this.element.classList.add("screencast"); 60 this._canvasElement.addEventListener('mousedown', this._handleMouseEvent.bin d(this), false);
61 61 this._canvasElement.addEventListener('mouseup', this._handleMouseEvent.bind( this), false);
62 this._createNavigationBar(); 62 this._canvasElement.addEventListener('mousemove', this._handleMouseEvent.bin d(this), false);
63 63 this._canvasElement.addEventListener('mousewheel', this._handleMouseEvent.bi nd(this), false);
64 this._viewportElement = this.element.createChild("div", "screencast-view port hidden"); 64 this._canvasElement.addEventListener('click', this._handleMouseEvent.bind(th is), false);
65 this._canvasContainerElement = this._viewportElement.createChild("div", "screencast-canvas-container"); 65 this._canvasElement.addEventListener('contextmenu', this._handleContextMenuE vent.bind(this), false);
66 this._glassPaneElement = this._canvasContainerElement.createChild("div", "screencast-glasspane fill hidden"); 66 this._canvasElement.addEventListener('keydown', this._handleKeyEvent.bind(th is), false);
67 67 this._canvasElement.addEventListener('keyup', this._handleKeyEvent.bind(this ), false);
68 this._canvasElement = this._canvasContainerElement.createChild("canvas") ; 68 this._canvasElement.addEventListener('keypress', this._handleKeyEvent.bind(t his), false);
69 this._canvasElement.tabIndex = 1; 69 this._canvasElement.addEventListener('blur', this._handleBlurEvent.bind(this ), false);
70 this._canvasElement.addEventListener("mousedown", this._handleMouseEvent .bind(this), false); 70
71 this._canvasElement.addEventListener("mouseup", this._handleMouseEvent.b ind(this), false); 71 this._titleElement = this._canvasContainerElement.createChild('div', 'screen cast-element-title monospace hidden');
72 this._canvasElement.addEventListener("mousemove", this._handleMouseEvent .bind(this), false); 72 this._tagNameElement = this._titleElement.createChild('span', 'screencast-ta g-name');
73 this._canvasElement.addEventListener("mousewheel", this._handleMouseEven t.bind(this), false); 73 this._nodeIdElement = this._titleElement.createChild('span', 'screencast-nod e-id');
74 this._canvasElement.addEventListener("click", this._handleMouseEvent.bin d(this), false); 74 this._classNameElement = this._titleElement.createChild('span', 'screencast- class-name');
75 this._canvasElement.addEventListener("contextmenu", this._handleContextM enuEvent.bind(this), false); 75 this._titleElement.createTextChild(' ');
76 this._canvasElement.addEventListener("keydown", this._handleKeyEvent.bin d(this), false); 76 this._nodeWidthElement = this._titleElement.createChild('span');
77 this._canvasElement.addEventListener("keyup", this._handleKeyEvent.bind( this), false); 77 this._titleElement.createChild('span', 'screencast-px').textContent = 'px';
78 this._canvasElement.addEventListener("keypress", this._handleKeyEvent.bi nd(this), false); 78 this._titleElement.createTextChild(' \u00D7 ');
79 this._canvasElement.addEventListener("blur", this._handleBlurEvent.bind( this), false); 79 this._nodeHeightElement = this._titleElement.createChild('span');
80 80 this._titleElement.createChild('span', 'screencast-px').textContent = 'px';
81 this._titleElement = this._canvasContainerElement.createChild("div", "sc reencast-element-title monospace hidden"); 81 this._titleElement.style.top = '0';
82 this._tagNameElement = this._titleElement.createChild("span", "screencas t-tag-name"); 82 this._titleElement.style.left = '0';
83 this._nodeIdElement = this._titleElement.createChild("span", "screencast -node-id"); 83
84 this._classNameElement = this._titleElement.createChild("span", "screenc ast-class-name"); 84 this._imageElement = new Image();
85 this._titleElement.createTextChild(" "); 85 this._isCasting = false;
86 this._nodeWidthElement = this._titleElement.createChild("span"); 86 this._context = this._canvasElement.getContext('2d');
87 this._titleElement.createChild("span", "screencast-px").textContent = "p x"; 87 this._checkerboardPattern = this._createCheckerboardPattern(this._context);
88 this._titleElement.createTextChild(" \u00D7 "); 88
89 this._nodeHeightElement = this._titleElement.createChild("span"); 89 this._shortcuts = /** !Object.<number, function(Event=):boolean> */ ({});
90 this._titleElement.createChild("span", "screencast-px").textContent = "p x"; 90 this._shortcuts[WebInspector.KeyboardShortcut.makeKey('l', WebInspector.Keyb oardShortcut.Modifiers.Ctrl)] =
91 this._titleElement.style.top = "0"; 91 this._focusNavigationBar.bind(this);
92 this._titleElement.style.left = "0"; 92
93 93 this._resourceTreeModel.addEventListener(
94 this._imageElement = new Image(); 94 WebInspector.ResourceTreeModel.Events.ScreencastFrame, this._screencastF rame, this);
95 this._isCasting = false; 95 this._resourceTreeModel.addEventListener(
96 this._context = this._canvasElement.getContext("2d"); 96 WebInspector.ResourceTreeModel.Events.ScreencastVisibilityChanged, this. _screencastVisibilityChanged, this);
97 this._checkerboardPattern = this._createCheckerboardPattern(this._contex t); 97
98 98 WebInspector.targetManager.addEventListener(
99 this._shortcuts = /** !Object.<number, function(Event=):boolean> */ ({}) ; 99 WebInspector.TargetManager.Events.SuspendStateChanged, this._onSuspendSt ateChange, this);
100 this._shortcuts[WebInspector.KeyboardShortcut.makeKey("l", WebInspector. KeyboardShortcut.Modifiers.Ctrl)] = this._focusNavigationBar.bind(this); 100 this._updateGlasspane();
101 101 }
102 this._resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel. Events.ScreencastFrame, this._screencastFrame, this); 102
103 this._resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel. Events.ScreencastVisibilityChanged, this._screencastVisibilityChanged, this); 103 /**
104 104 * @override
105 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.E vents.SuspendStateChanged, this._onSuspendStateChange, this); 105 */
106 this._updateGlasspane(); 106 wasShown() {
107 }, 107 this._startCasting();
108 108 }
109 wasShown: function() 109
110 { 110 /**
111 this._startCasting(); 111 * @override
112 }, 112 */
113 113 willHide() {
114 willHide: function() 114 this._stopCasting();
115 { 115 }
116 this._stopCasting(); 116
117 }, 117 _startCasting() {
118 118 if (WebInspector.targetManager.allTargetsSuspended())
119 _startCasting: function() 119 return;
120 { 120 if (this._isCasting)
121 if (WebInspector.targetManager.allTargetsSuspended()) 121 return;
122 return; 122 this._isCasting = true;
123 if (this._isCasting) 123
124 return; 124 const maxImageDimension = 2048;
125 this._isCasting = true; 125 var dimensions = this._viewportDimensions();
126 126 if (dimensions.width < 0 || dimensions.height < 0) {
127 const maxImageDimension = 2048; 127 this._isCasting = false;
128 var dimensions = this._viewportDimensions(); 128 return;
129 if (dimensions.width < 0 || dimensions.height < 0) { 129 }
130 this._isCasting = false; 130 dimensions.width *= window.devicePixelRatio;
131 return; 131 dimensions.height *= window.devicePixelRatio;
132 } 132 this._target.pageAgent().startScreencast(
133 dimensions.width *= window.devicePixelRatio; 133 'jpeg', 80, Math.min(maxImageDimension, dimensions.width), Math.min(maxI mageDimension, dimensions.height));
134 dimensions.height *= window.devicePixelRatio; 134 this._target.emulationAgent().setTouchEmulationEnabled(true);
135 this._target.pageAgent().startScreencast("jpeg", 80, Math.min(maxImageDi mension, dimensions.width), Math.min(maxImageDimension, dimensions.height)); 135 this._domModel.setHighlighter(this);
136 this._target.emulationAgent().setTouchEmulationEnabled(true); 136 }
137 this._domModel.setHighlighter(this); 137
138 }, 138 _stopCasting() {
139 139 if (!this._isCasting)
140 _stopCasting: function() 140 return;
141 { 141 this._isCasting = false;
142 if (!this._isCasting) 142 this._target.pageAgent().stopScreencast();
143 return; 143 this._target.emulationAgent().setTouchEmulationEnabled(false);
144 this._isCasting = false; 144 this._domModel.setHighlighter(null);
145 this._target.pageAgent().stopScreencast(); 145 }
146 this._target.emulationAgent().setTouchEmulationEnabled(false); 146
147 this._domModel.setHighlighter(null); 147 /**
148 }, 148 * @param {!WebInspector.Event} event
149 */
150 _screencastFrame(event) {
151 var metadata = /** type {PageAgent.ScreencastFrameMetadata} */ (event.data.m etadata);
152 var base64Data = /** type {string} */ (event.data.data);
153 this._imageElement.src = 'data:image/jpg;base64,' + base64Data;
154 this._pageScaleFactor = metadata.pageScaleFactor;
155 this._screenOffsetTop = metadata.offsetTop;
156 this._scrollOffsetX = metadata.scrollOffsetX;
157 this._scrollOffsetY = metadata.scrollOffsetY;
158
159 var deviceSizeRatio = metadata.deviceHeight / metadata.deviceWidth;
160 var dimensionsCSS = this._viewportDimensions();
161
162 this._imageZoom = Math.min(
163 dimensionsCSS.width / this._imageElement.naturalWidth,
164 dimensionsCSS.height / (this._imageElement.naturalWidth * deviceSizeRati o));
165 this._viewportElement.classList.remove('hidden');
166 var bordersSize = WebInspector.ScreencastView._bordersSize;
167 if (this._imageZoom < 1.01 / window.devicePixelRatio)
168 this._imageZoom = 1 / window.devicePixelRatio;
169 this._screenZoom = this._imageElement.naturalWidth * this._imageZoom / metad ata.deviceWidth;
170 this._viewportElement.style.width = metadata.deviceWidth * this._screenZoom + bordersSize + 'px';
171 this._viewportElement.style.height = metadata.deviceHeight * this._screenZoo m + bordersSize + 'px';
172
173 this.highlightDOMNode(this._highlightNode, this._highlightConfig);
174 }
175
176 _isGlassPaneActive() {
177 return !this._glassPaneElement.classList.contains('hidden');
178 }
179
180 /**
181 * @param {!WebInspector.Event} event
182 */
183 _screencastVisibilityChanged(event) {
184 this._targetInactive = !event.data.visible;
185 this._updateGlasspane();
186 }
187
188 /**
189 * @param {!WebInspector.Event} event
190 */
191 _onSuspendStateChange(event) {
192 if (WebInspector.targetManager.allTargetsSuspended())
193 this._stopCasting();
194 else
195 this._startCasting();
196 this._updateGlasspane();
197 }
198
199 _updateGlasspane() {
200 if (this._targetInactive) {
201 this._glassPaneElement.textContent = WebInspector.UIString('The tab is ina ctive');
202 this._glassPaneElement.classList.remove('hidden');
203 } else if (WebInspector.targetManager.allTargetsSuspended()) {
204 this._glassPaneElement.textContent = WebInspector.UIString('Profiling in p rogress');
205 this._glassPaneElement.classList.remove('hidden');
206 } else {
207 this._glassPaneElement.classList.add('hidden');
208 }
209 }
210
211 /**
212 * @param {!Event} event
213 */
214 _handleMouseEvent(event) {
215 if (this._isGlassPaneActive()) {
216 event.consume();
217 return;
218 }
219
220 if (!this._pageScaleFactor)
221 return;
222
223 if (!this._inspectModeConfig || event.type === 'mousewheel') {
224 this._simulateTouchForMouseEvent(event);
225 event.preventDefault();
226 if (event.type === 'mousedown')
227 this._canvasElement.focus();
228 return;
229 }
230
231 var position = this._convertIntoScreenSpace(event);
232 this._domModel.nodeForLocation(
233 position.x / this._pageScaleFactor + this._scrollOffsetX,
234 position.y / this._pageScaleFactor + this._scrollOffsetY, callback.bind( this));
149 235
150 /** 236 /**
151 * @param {!WebInspector.Event} event 237 * @param {?WebInspector.DOMNode} node
238 * @this {WebInspector.ScreencastView}
152 */ 239 */
153 _screencastFrame: function(event) 240 function callback(node) {
154 { 241 if (!node)
155 var metadata = /** type {PageAgent.ScreencastFrameMetadata} */(event.dat a.metadata); 242 return;
156 var base64Data = /** type {string} */(event.data.data); 243 if (event.type === 'mousemove') {
157 this._imageElement.src = "data:image/jpg;base64," + base64Data; 244 this.highlightDOMNode(node, this._inspectModeConfig);
158 this._pageScaleFactor = metadata.pageScaleFactor; 245 this._domModel.nodeHighlightRequested(node.id);
159 this._screenOffsetTop = metadata.offsetTop; 246 } else if (event.type === 'click') {
160 this._scrollOffsetX = metadata.scrollOffsetX; 247 WebInspector.Revealer.reveal(node);
161 this._scrollOffsetY = metadata.scrollOffsetY; 248 }
162 249 }
163 var deviceSizeRatio = metadata.deviceHeight / metadata.deviceWidth; 250 }
164 var dimensionsCSS = this._viewportDimensions(); 251
165 252 /**
166 this._imageZoom = Math.min(dimensionsCSS.width / this._imageElement.natu ralWidth, dimensionsCSS.height / (this._imageElement.naturalWidth * deviceSizeRa tio)); 253 * @param {!Event} event
167 this._viewportElement.classList.remove("hidden"); 254 */
168 var bordersSize = WebInspector.ScreencastView._bordersSize; 255 _handleKeyEvent(event) {
169 if (this._imageZoom < 1.01 / window.devicePixelRatio) 256 if (this._isGlassPaneActive()) {
170 this._imageZoom = 1 / window.devicePixelRatio; 257 event.consume();
171 this._screenZoom = this._imageElement.naturalWidth * this._imageZoom / m etadata.deviceWidth; 258 return;
172 this._viewportElement.style.width = metadata.deviceWidth * this._screenZ oom + bordersSize + "px"; 259 }
173 this._viewportElement.style.height = metadata.deviceHeight * this._scree nZoom + bordersSize + "px"; 260
174 261 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(/** @type { !KeyboardEvent} */ (event));
175 this.highlightDOMNode(this._highlightNode, this._highlightConfig); 262 var handler = this._shortcuts[shortcutKey];
176 }, 263 if (handler && handler(event)) {
177 264 event.consume();
178 _isGlassPaneActive: function() 265 return;
179 { 266 }
180 return !this._glassPaneElement.classList.contains("hidden"); 267
181 }, 268 var type;
269 switch (event.type) {
270 case 'keydown':
271 type = 'keyDown';
272 break;
273 case 'keyup':
274 type = 'keyUp';
275 break;
276 case 'keypress':
277 type = 'char';
278 break;
279 default:
280 return;
281 }
282
283 var text = event.type === 'keypress' ? String.fromCharCode(event.charCode) : undefined;
284 this._target.inputAgent().invoke_dispatchKeyEvent({
285 type: type,
286 modifiers: this._modifiersForEvent(event),
287 timestamp: event.timeStamp / 1000,
288 text: text,
289 unmodifiedText: text ? text.toLowerCase() : undefined,
290 keyIdentifier: event.keyIdentifier,
291 code: event.code,
292 key: event.key,
293 windowsVirtualKeyCode: event.keyCode,
294 nativeVirtualKeyCode: event.keyCode,
295 autoRepeat: false,
296 isKeypad: false,
297 isSystemKey: false
298 });
299 event.consume();
300 this._canvasElement.focus();
301 }
302
303 /**
304 * @param {!Event} event
305 */
306 _handleContextMenuEvent(event) {
307 event.consume(true);
308 }
309
310 /**
311 * @param {!Event} event
312 */
313 _simulateTouchForMouseEvent(event) {
314 const buttons = {0: 'none', 1: 'left', 2: 'middle', 3: 'right'};
315 const types = {
316 'mousedown': 'mousePressed',
317 'mouseup': 'mouseReleased',
318 'mousemove': 'mouseMoved',
319 'mousewheel': 'mouseWheel'
320 };
321 if (!(event.type in types) || !(event.which in buttons))
322 return;
323 if (event.type !== 'mousewheel' && buttons[event.which] === 'none')
324 return;
325
326 if (event.type === 'mousedown' || typeof this._eventScreenOffsetTop === 'und efined')
327 this._eventScreenOffsetTop = this._screenOffsetTop;
328
329 var modifiers =
330 (event.altKey ? 1 : 0) | (event.ctrlKey ? 2 : 0) | (event.metaKey ? 4 : 0) | (event.shiftKey ? 8 : 0);
331
332 var convertedPosition = this._zoomIntoScreenSpace(event);
333 convertedPosition.y = Math.round(convertedPosition.y - this._eventScreenOffs etTop);
334 var params = {
335 type: types[event.type],
336 x: convertedPosition.x,
337 y: convertedPosition.y,
338 modifiers: modifiers,
339 timestamp: event.timeStamp / 1000,
340 button: buttons[event.which],
341 clickCount: 0
342 };
343 if (event.type === 'mousewheel') {
344 params.deltaX = event.wheelDeltaX / this._screenZoom;
345 params.deltaY = event.wheelDeltaY / this._screenZoom;
346 } else {
347 this._eventParams = params;
348 }
349 if (event.type === 'mouseup')
350 delete this._eventScreenOffsetTop;
351 this._target.inputAgent().invoke_emulateTouchFromMouseEvent(params);
352 }
353
354 /**
355 * @param {!Event} event
356 */
357 _handleBlurEvent(event) {
358 if (typeof this._eventScreenOffsetTop !== 'undefined') {
359 var params = this._eventParams;
360 delete this._eventParams;
361 params.type = 'mouseReleased';
362 this._target.inputAgent().invoke_emulateTouchFromMouseEvent(params);
363 }
364 }
365
366 /**
367 * @param {!Event} event
368 * @return {!{x: number, y: number}}
369 */
370 _zoomIntoScreenSpace(event) {
371 var position = {};
372 position.x = Math.round(event.offsetX / this._screenZoom);
373 position.y = Math.round(event.offsetY / this._screenZoom);
374 return position;
375 }
376
377 /**
378 * @param {!Event} event
379 * @return {!{x: number, y: number}}
380 */
381 _convertIntoScreenSpace(event) {
382 var position = this._zoomIntoScreenSpace(event);
383 position.y = Math.round(position.y - this._screenOffsetTop);
384 return position;
385 }
386
387 /**
388 * @param {!Event} event
389 * @return {number}
390 */
391 _modifiersForEvent(event) {
392 var modifiers = 0;
393 if (event.altKey)
394 modifiers = 1;
395 if (event.ctrlKey)
396 modifiers += 2;
397 if (event.metaKey)
398 modifiers += 4;
399 if (event.shiftKey)
400 modifiers += 8;
401 return modifiers;
402 }
403
404 /**
405 * @override
406 */
407 onResize() {
408 if (this._deferredCasting) {
409 clearTimeout(this._deferredCasting);
410 delete this._deferredCasting;
411 }
412
413 this._stopCasting();
414 this._deferredCasting = setTimeout(this._startCasting.bind(this), 100);
415 }
416
417 /**
418 * @override
419 * @param {?WebInspector.DOMNode} node
420 * @param {?DOMAgent.HighlightConfig} config
421 * @param {!DOMAgent.BackendNodeId=} backendNodeId
422 * @param {!RuntimeAgent.RemoteObjectId=} objectId
423 */
424 highlightDOMNode(node, config, backendNodeId, objectId) {
425 this._highlightNode = node;
426 this._highlightConfig = config;
427 if (!node) {
428 this._model = null;
429 this._config = null;
430 this._node = null;
431 this._titleElement.classList.add('hidden');
432 this._repaint();
433 return;
434 }
435
436 this._node = node;
437 node.boxModel(callback.bind(this));
182 438
183 /** 439 /**
184 * @param {!WebInspector.Event} event 440 * @param {?DOMAgent.BoxModel} model
441 * @this {WebInspector.ScreencastView}
185 */ 442 */
186 _screencastVisibilityChanged: function(event) 443 function callback(model) {
187 { 444 if (!model || !this._pageScaleFactor) {
188 this._targetInactive = !event.data.visible; 445 this._repaint();
189 this._updateGlasspane(); 446 return;
190 }, 447 }
191 448 this._model = this._scaleModel(model);
192 /** 449 this._config = config;
193 * @param {!WebInspector.Event} event 450 this._repaint();
194 */ 451 }
195 _onSuspendStateChange: function(event) 452 }
196 { 453
197 if (WebInspector.targetManager.allTargetsSuspended()) 454 /**
198 this._stopCasting(); 455 * @param {!DOMAgent.BoxModel} model
199 else 456 * @return {!DOMAgent.BoxModel}
200 this._startCasting(); 457 */
201 this._updateGlasspane(); 458 _scaleModel(model) {
202 },
203
204 _updateGlasspane: function()
205 {
206 if (this._targetInactive) {
207 this._glassPaneElement.textContent = WebInspector.UIString("The tab is inactive");
208 this._glassPaneElement.classList.remove("hidden");
209 } else if (WebInspector.targetManager.allTargetsSuspended()) {
210 this._glassPaneElement.textContent = WebInspector.UIString("Profilin g in progress");
211 this._glassPaneElement.classList.remove("hidden");
212 } else {
213 this._glassPaneElement.classList.add("hidden");
214 }
215 },
216
217 /**
218 * @param {!Event} event
219 */
220 _handleMouseEvent: function(event)
221 {
222 if (this._isGlassPaneActive()) {
223 event.consume();
224 return;
225 }
226
227 if (!this._pageScaleFactor)
228 return;
229
230 if (!this._inspectModeConfig || event.type === "mousewheel") {
231 this._simulateTouchForMouseEvent(event);
232 event.preventDefault();
233 if (event.type === "mousedown")
234 this._canvasElement.focus();
235 return;
236 }
237
238 var position = this._convertIntoScreenSpace(event);
239 this._domModel.nodeForLocation(position.x / this._pageScaleFactor + this ._scrollOffsetX, position.y / this._pageScaleFactor + this._scrollOffsetY, callb ack.bind(this));
240
241 /**
242 * @param {?WebInspector.DOMNode} node
243 * @this {WebInspector.ScreencastView}
244 */
245 function callback(node)
246 {
247 if (!node)
248 return;
249 if (event.type === "mousemove") {
250 this.highlightDOMNode(node, this._inspectModeConfig);
251 this._domModel.nodeHighlightRequested(node.id);
252 } else if (event.type === "click") {
253 WebInspector.Revealer.reveal(node);
254 }
255 }
256 },
257
258 /**
259 * @param {!Event} event
260 */
261 _handleKeyEvent: function(event)
262 {
263 if (this._isGlassPaneActive()) {
264 event.consume();
265 return;
266 }
267
268 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(/** @ty pe {!KeyboardEvent} */ (event));
269 var handler = this._shortcuts[shortcutKey];
270 if (handler && handler(event)) {
271 event.consume();
272 return;
273 }
274
275 var type;
276 switch (event.type) {
277 case "keydown": type = "keyDown"; break;
278 case "keyup": type = "keyUp"; break;
279 case "keypress": type = "char"; break;
280 default: return;
281 }
282
283 var text = event.type === "keypress" ? String.fromCharCode(event.charCod e) : undefined;
284 this._target.inputAgent().invoke_dispatchKeyEvent({
285 type: type,
286 modifiers: this._modifiersForEvent(event),
287 timestamp: event.timeStamp / 1000,
288 text: text,
289 unmodifiedText: text ? text.toLowerCase() : undefined,
290 keyIdentifier: event.keyIdentifier,
291 code: event.code,
292 key: event.key,
293 windowsVirtualKeyCode: event.keyCode,
294 nativeVirtualKeyCode: event.keyCode,
295 autoRepeat: false,
296 isKeypad: false,
297 isSystemKey: false});
298 event.consume();
299 this._canvasElement.focus();
300 },
301
302 /**
303 * @param {!Event} event
304 */
305 _handleContextMenuEvent: function(event)
306 {
307 event.consume(true);
308 },
309
310 /**
311 * @param {!Event} event
312 */
313 _simulateTouchForMouseEvent: function(event)
314 {
315 const buttons = {0: "none", 1: "left", 2: "middle", 3: "right"};
316 const types = {"mousedown" : "mousePressed", "mouseup": "mouseReleased", "mousemove": "mouseMoved", "mousewheel": "mouseWheel"};
317 if (!(event.type in types) || !(event.which in buttons))
318 return;
319 if (event.type !== "mousewheel" && buttons[event.which] === "none")
320 return;
321
322 if (event.type === "mousedown" || typeof this._eventScreenOffsetTop === "undefined")
323 this._eventScreenOffsetTop = this._screenOffsetTop;
324
325 var modifiers = (event.altKey ? 1 : 0) | (event.ctrlKey ? 2 : 0) | (even t.metaKey ? 4 : 0) | (event.shiftKey ? 8 : 0);
326
327 var convertedPosition = this._zoomIntoScreenSpace(event);
328 convertedPosition.y = Math.round(convertedPosition.y - this._eventScreen OffsetTop);
329 var params = {type: types[event.type], x: convertedPosition.x, y: conver tedPosition.y, modifiers: modifiers, timestamp: event.timeStamp / 1000, button: buttons[event.which], clickCount: 0};
330 if (event.type === "mousewheel") {
331 params.deltaX = event.wheelDeltaX / this._screenZoom;
332 params.deltaY = event.wheelDeltaY / this._screenZoom;
333 } else {
334 this._eventParams = params;
335 }
336 if (event.type === "mouseup")
337 delete this._eventScreenOffsetTop;
338 this._target.inputAgent().invoke_emulateTouchFromMouseEvent(params);
339 },
340
341 /**
342 * @param {!Event} event
343 */
344 _handleBlurEvent: function(event)
345 {
346 if (typeof this._eventScreenOffsetTop !== "undefined") {
347 var params = this._eventParams;
348 delete this._eventParams;
349 params.type = "mouseReleased";
350 this._target.inputAgent().invoke_emulateTouchFromMouseEvent(params);
351 }
352 },
353
354 /**
355 * @param {!Event} event
356 * @return {!{x: number, y: number}}
357 */
358 _zoomIntoScreenSpace: function(event)
359 {
360 var position = {};
361 position.x = Math.round(event.offsetX / this._screenZoom);
362 position.y = Math.round(event.offsetY / this._screenZoom);
363 return position;
364 },
365
366 /**
367 * @param {!Event} event
368 * @return {!{x: number, y: number}}
369 */
370 _convertIntoScreenSpace: function(event)
371 {
372 var position = this._zoomIntoScreenSpace(event);
373 position.y = Math.round(position.y - this._screenOffsetTop);
374 return position;
375 },
376
377 /**
378 * @param {!Event} event
379 * @return {number}
380 */
381 _modifiersForEvent: function(event)
382 {
383 var modifiers = 0;
384 if (event.altKey)
385 modifiers = 1;
386 if (event.ctrlKey)
387 modifiers += 2;
388 if (event.metaKey)
389 modifiers += 4;
390 if (event.shiftKey)
391 modifiers += 8;
392 return modifiers;
393 },
394
395 onResize: function()
396 {
397 if (this._deferredCasting) {
398 clearTimeout(this._deferredCasting);
399 delete this._deferredCasting;
400 }
401
402 this._stopCasting();
403 this._deferredCasting = setTimeout(this._startCasting.bind(this), 100);
404 },
405
406 /**
407 * @override
408 * @param {?WebInspector.DOMNode} node
409 * @param {?DOMAgent.HighlightConfig} config
410 * @param {!DOMAgent.BackendNodeId=} backendNodeId
411 * @param {!RuntimeAgent.RemoteObjectId=} objectId
412 */
413 highlightDOMNode: function(node, config, backendNodeId, objectId)
414 {
415 this._highlightNode = node;
416 this._highlightConfig = config;
417 if (!node) {
418 this._model = null;
419 this._config = null;
420 this._node = null;
421 this._titleElement.classList.add("hidden");
422 this._repaint();
423 return;
424 }
425
426 this._node = node;
427 node.boxModel(callback.bind(this));
428
429 /**
430 * @param {?DOMAgent.BoxModel} model
431 * @this {WebInspector.ScreencastView}
432 */
433 function callback(model)
434 {
435 if (!model || !this._pageScaleFactor) {
436 this._repaint();
437 return;
438 }
439 this._model = this._scaleModel(model);
440 this._config = config;
441 this._repaint();
442 }
443 },
444
445 /**
446 * @param {!DOMAgent.BoxModel} model
447 * @return {!DOMAgent.BoxModel}
448 */
449 _scaleModel: function(model)
450 {
451 /**
452 * @param {!DOMAgent.Quad} quad
453 * @this {WebInspector.ScreencastView}
454 */
455 function scaleQuad(quad)
456 {
457 for (var i = 0; i < quad.length; i += 2) {
458 quad[i] = quad[i] * this._screenZoom;
459 quad[i + 1] = (quad[i + 1] + this._screenOffsetTop) * this._scre enZoom;
460 }
461 }
462
463 scaleQuad.call(this, model.content);
464 scaleQuad.call(this, model.padding);
465 scaleQuad.call(this, model.border);
466 scaleQuad.call(this, model.margin);
467 return model;
468 },
469
470 _repaint: function()
471 {
472 var model = this._model;
473 var config = this._config;
474
475 var canvasWidth = this._canvasElement.getBoundingClientRect().width;
476 var canvasHeight = this._canvasElement.getBoundingClientRect().height;
477 this._canvasElement.width = window.devicePixelRatio * canvasWidth;
478 this._canvasElement.height = window.devicePixelRatio * canvasHeight;
479
480 this._context.save();
481 this._context.scale(window.devicePixelRatio, window.devicePixelRatio);
482
483 // Paint top and bottom gutter.
484 this._context.save();
485 this._context.fillStyle = this._checkerboardPattern;
486 this._context.fillRect(0, 0, canvasWidth, this._screenOffsetTop * this._ screenZoom);
487 this._context.fillRect(0, this._screenOffsetTop * this._screenZoom + thi s._imageElement.naturalHeight * this._imageZoom, canvasWidth, canvasHeight);
488 this._context.restore();
489
490 if (model && config) {
491 this._context.save();
492 const transparentColor = "rgba(0, 0, 0, 0)";
493 var quads = [];
494 if (model.content && config.contentColor !== transparentColor)
495 quads.push({quad: model.content, color: config.contentColor});
496 if (model.padding && config.paddingColor !== transparentColor)
497 quads.push({quad: model.padding, color: config.paddingColor});
498 if (model.border && config.borderColor !== transparentColor)
499 quads.push({quad: model.border, color: config.borderColor});
500 if (model.margin && config.marginColor !== transparentColor)
501 quads.push({quad: model.margin, color: config.marginColor});
502
503 for (var i = quads.length - 1; i > 0; --i)
504 this._drawOutlinedQuadWithClip(quads[i].quad, quads[i - 1].quad, quads[i].color);
505 if (quads.length > 0)
506 this._drawOutlinedQuad(quads[0].quad, quads[0].color);
507 this._context.restore();
508
509 this._drawElementTitle();
510
511 this._context.globalCompositeOperation = "destination-over";
512 }
513
514 this._context.drawImage(this._imageElement, 0, this._screenOffsetTop * t his._screenZoom, this._imageElement.naturalWidth * this._imageZoom, this._imageE lement.naturalHeight * this._imageZoom);
515 this._context.restore();
516
517 },
518
519 /**
520 * @param {!DOMAgent.RGBA} color
521 * @return {string}
522 */
523 _cssColor: function(color)
524 {
525 if (!color)
526 return "transparent";
527 return WebInspector.Color.fromRGBA([color.r, color.g, color.b, color.a]) .asString(WebInspector.Color.Format.RGBA) || "";
528 },
529
530 /** 459 /**
531 * @param {!DOMAgent.Quad} quad 460 * @param {!DOMAgent.Quad} quad
532 * @return {!CanvasRenderingContext2D} 461 * @this {WebInspector.ScreencastView}
533 */ 462 */
534 _quadToPath: function(quad) 463 function scaleQuad(quad) {
535 { 464 for (var i = 0; i < quad.length; i += 2) {
536 this._context.beginPath(); 465 quad[i] = quad[i] * this._screenZoom;
537 this._context.moveTo(quad[0], quad[1]); 466 quad[i + 1] = (quad[i + 1] + this._screenOffsetTop) * this._screenZoom;
538 this._context.lineTo(quad[2], quad[3]); 467 }
539 this._context.lineTo(quad[4], quad[5]); 468 }
540 this._context.lineTo(quad[6], quad[7]); 469
541 this._context.closePath(); 470 scaleQuad.call(this, model.content);
542 return this._context; 471 scaleQuad.call(this, model.padding);
543 }, 472 scaleQuad.call(this, model.border);
544 473 scaleQuad.call(this, model.margin);
545 /** 474 return model;
546 * @param {!DOMAgent.Quad} quad 475 }
547 * @param {!DOMAgent.RGBA} fillColor 476
548 */ 477 _repaint() {
549 _drawOutlinedQuad: function(quad, fillColor) 478 var model = this._model;
550 { 479 var config = this._config;
551 this._context.save(); 480
552 this._context.lineWidth = 2; 481 var canvasWidth = this._canvasElement.getBoundingClientRect().width;
553 this._quadToPath(quad).clip(); 482 var canvasHeight = this._canvasElement.getBoundingClientRect().height;
554 this._context.fillStyle = this._cssColor(fillColor); 483 this._canvasElement.width = window.devicePixelRatio * canvasWidth;
555 this._context.fill(); 484 this._canvasElement.height = window.devicePixelRatio * canvasHeight;
556 this._context.restore(); 485
557 }, 486 this._context.save();
558 487 this._context.scale(window.devicePixelRatio, window.devicePixelRatio);
559 /** 488
560 * @param {!DOMAgent.Quad} quad 489 // Paint top and bottom gutter.
561 * @param {!DOMAgent.Quad} clipQuad 490 this._context.save();
562 * @param {!DOMAgent.RGBA} fillColor 491 this._context.fillStyle = this._checkerboardPattern;
563 */ 492 this._context.fillRect(0, 0, canvasWidth, this._screenOffsetTop * this._scre enZoom);
564 _drawOutlinedQuadWithClip: function(quad, clipQuad, fillColor) 493 this._context.fillRect(
565 { 494 0, this._screenOffsetTop * this._screenZoom + this._imageElement.natural Height * this._imageZoom, canvasWidth,
566 this._context.fillStyle = this._cssColor(fillColor); 495 canvasHeight);
567 this._context.save(); 496 this._context.restore();
568 this._context.lineWidth = 0; 497
569 this._quadToPath(quad).fill(); 498 if (model && config) {
570 this._context.globalCompositeOperation = "destination-out"; 499 this._context.save();
571 this._context.fillStyle = "red"; 500 const transparentColor = 'rgba(0, 0, 0, 0)';
572 this._quadToPath(clipQuad).fill(); 501 var quads = [];
573 this._context.restore(); 502 if (model.content && config.contentColor !== transparentColor)
574 }, 503 quads.push({quad: model.content, color: config.contentColor});
575 504 if (model.padding && config.paddingColor !== transparentColor)
576 _drawElementTitle: function() 505 quads.push({quad: model.padding, color: config.paddingColor});
577 { 506 if (model.border && config.borderColor !== transparentColor)
578 if (!this._node) 507 quads.push({quad: model.border, color: config.borderColor});
579 return; 508 if (model.margin && config.marginColor !== transparentColor)
580 509 quads.push({quad: model.margin, color: config.marginColor});
581 var canvasWidth = this._canvasElement.getBoundingClientRect().width; 510
582 var canvasHeight = this._canvasElement.getBoundingClientRect().height; 511 for (var i = quads.length - 1; i > 0; --i)
583 512 this._drawOutlinedQuadWithClip(quads[i].quad, quads[i - 1].quad, quads[i ].color);
584 var lowerCaseName = this._node.localName() || this._node.nodeName().toLo werCase(); 513 if (quads.length > 0)
585 this._tagNameElement.textContent = lowerCaseName; 514 this._drawOutlinedQuad(quads[0].quad, quads[0].color);
586 this._nodeIdElement.textContent = this._node.getAttribute("id") ? "#" + this._node.getAttribute("id") : ""; 515 this._context.restore();
587 this._nodeIdElement.textContent = this._node.getAttribute("id") ? "#" + this._node.getAttribute("id") : ""; 516
588 var className = this._node.getAttribute("class"); 517 this._drawElementTitle();
589 if (className && className.length > 50) 518
590 className = className.substring(0, 50) + "\u2026"; 519 this._context.globalCompositeOperation = 'destination-over';
591 this._classNameElement.textContent = className || ""; 520 }
592 this._nodeWidthElement.textContent = this._model.width; 521
593 this._nodeHeightElement.textContent = this._model.height; 522 this._context.drawImage(
594 523 this._imageElement, 0, this._screenOffsetTop * this._screenZoom,
595 this._titleElement.classList.remove("hidden"); 524 this._imageElement.naturalWidth * this._imageZoom, this._imageElement.na turalHeight * this._imageZoom);
596 var titleWidth = this._titleElement.offsetWidth + 6; 525 this._context.restore();
597 var titleHeight = this._titleElement.offsetHeight + 4; 526 }
598 527
599 var anchorTop = this._model.margin[1]; 528 /**
600 var anchorBottom = this._model.margin[7]; 529 * @param {!DOMAgent.RGBA} color
601 530 * @return {string}
602 const arrowHeight = 7; 531 */
603 var renderArrowUp = false; 532 _cssColor(color) {
604 var renderArrowDown = false; 533 if (!color)
605 534 return 'transparent';
606 var boxX = Math.max(2, this._model.margin[0]); 535 return WebInspector.Color.fromRGBA([color.r, color.g, color.b, color.a]).asS tring(WebInspector.Color.Format.RGBA) ||
607 if (boxX + titleWidth > canvasWidth) 536 '';
608 boxX = canvasWidth - titleWidth - 2; 537 }
609 538
610 var boxY; 539 /**
611 if (anchorTop > canvasHeight) { 540 * @param {!DOMAgent.Quad} quad
612 boxY = canvasHeight - titleHeight - arrowHeight; 541 * @return {!CanvasRenderingContext2D}
613 renderArrowDown = true; 542 */
614 } else if (anchorBottom < 0) { 543 _quadToPath(quad) {
615 boxY = arrowHeight; 544 this._context.beginPath();
616 renderArrowUp = true; 545 this._context.moveTo(quad[0], quad[1]);
617 } else if (anchorBottom + titleHeight + arrowHeight < canvasHeight) { 546 this._context.lineTo(quad[2], quad[3]);
618 boxY = anchorBottom + arrowHeight - 4; 547 this._context.lineTo(quad[4], quad[5]);
619 renderArrowUp = true; 548 this._context.lineTo(quad[6], quad[7]);
620 } else if (anchorTop - titleHeight - arrowHeight > 0) { 549 this._context.closePath();
621 boxY = anchorTop - titleHeight - arrowHeight + 3; 550 return this._context;
622 renderArrowDown = true; 551 }
623 } else 552
624 boxY = arrowHeight; 553 /**
625 554 * @param {!DOMAgent.Quad} quad
626 this._context.save(); 555 * @param {!DOMAgent.RGBA} fillColor
627 this._context.translate(0.5, 0.5); 556 */
628 this._context.beginPath(); 557 _drawOutlinedQuad(quad, fillColor) {
629 this._context.moveTo(boxX, boxY); 558 this._context.save();
630 if (renderArrowUp) { 559 this._context.lineWidth = 2;
631 this._context.lineTo(boxX + 2 * arrowHeight, boxY); 560 this._quadToPath(quad).clip();
632 this._context.lineTo(boxX + 3 * arrowHeight, boxY - arrowHeight); 561 this._context.fillStyle = this._cssColor(fillColor);
633 this._context.lineTo(boxX + 4 * arrowHeight, boxY); 562 this._context.fill();
634 } 563 this._context.restore();
635 this._context.lineTo(boxX + titleWidth, boxY); 564 }
636 this._context.lineTo(boxX + titleWidth, boxY + titleHeight); 565
637 if (renderArrowDown) { 566 /**
638 this._context.lineTo(boxX + 4 * arrowHeight, boxY + titleHeight); 567 * @param {!DOMAgent.Quad} quad
639 this._context.lineTo(boxX + 3 * arrowHeight, boxY + titleHeight + ar rowHeight); 568 * @param {!DOMAgent.Quad} clipQuad
640 this._context.lineTo(boxX + 2 * arrowHeight, boxY + titleHeight); 569 * @param {!DOMAgent.RGBA} fillColor
641 } 570 */
642 this._context.lineTo(boxX, boxY + titleHeight); 571 _drawOutlinedQuadWithClip(quad, clipQuad, fillColor) {
643 this._context.closePath(); 572 this._context.fillStyle = this._cssColor(fillColor);
644 this._context.fillStyle = "rgb(255, 255, 194)"; 573 this._context.save();
645 this._context.fill(); 574 this._context.lineWidth = 0;
646 this._context.strokeStyle = "rgb(128, 128, 128)"; 575 this._quadToPath(quad).fill();
647 this._context.stroke(); 576 this._context.globalCompositeOperation = 'destination-out';
648 577 this._context.fillStyle = 'red';
649 this._context.restore(); 578 this._quadToPath(clipQuad).fill();
650 579 this._context.restore();
651 this._titleElement.style.top = (boxY + 3) + "px"; 580 }
652 this._titleElement.style.left = (boxX + 3) + "px"; 581
653 }, 582 _drawElementTitle() {
654 583 if (!this._node)
655 /** 584 return;
656 * @return {!{width: number, height: number}} 585
657 */ 586 var canvasWidth = this._canvasElement.getBoundingClientRect().width;
658 _viewportDimensions: function() 587 var canvasHeight = this._canvasElement.getBoundingClientRect().height;
659 { 588
660 const gutterSize = 30; 589 var lowerCaseName = this._node.localName() || this._node.nodeName().toLowerC ase();
661 const bordersSize = WebInspector.ScreencastView._bordersSize; 590 this._tagNameElement.textContent = lowerCaseName;
662 var width = this.element.offsetWidth - bordersSize - gutterSize; 591 this._nodeIdElement.textContent = this._node.getAttribute('id') ? '#' + this ._node.getAttribute('id') : '';
663 var height = this.element.offsetHeight - bordersSize - gutterSize - WebI nspector.ScreencastView._navBarHeight; 592 this._nodeIdElement.textContent = this._node.getAttribute('id') ? '#' + this ._node.getAttribute('id') : '';
664 return { width: width, height: height }; 593 var className = this._node.getAttribute('class');
665 }, 594 if (className && className.length > 50)
666 595 className = className.substring(0, 50) + '\u2026';
667 /** 596 this._classNameElement.textContent = className || '';
668 * @override 597 this._nodeWidthElement.textContent = this._model.width;
669 * @param {!DOMAgent.InspectMode} mode 598 this._nodeHeightElement.textContent = this._model.height;
670 * @param {!DOMAgent.HighlightConfig} config 599
671 * @param {function(?Protocol.Error)=} callback 600 this._titleElement.classList.remove('hidden');
672 */ 601 var titleWidth = this._titleElement.offsetWidth + 6;
673 setInspectMode: function(mode, config, callback) 602 var titleHeight = this._titleElement.offsetHeight + 4;
674 { 603
675 this._inspectModeConfig = mode !== DOMAgent.InspectMode.None ? config : null; 604 var anchorTop = this._model.margin[1];
676 if (callback) 605 var anchorBottom = this._model.margin[7];
677 callback(null); 606
678 }, 607 const arrowHeight = 7;
679 608 var renderArrowUp = false;
680 /** 609 var renderArrowDown = false;
681 * @override 610
682 * @param {!PageAgent.FrameId} frameId 611 var boxX = Math.max(2, this._model.margin[0]);
683 */ 612 if (boxX + titleWidth > canvasWidth)
684 highlightFrame: function(frameId) 613 boxX = canvasWidth - titleWidth - 2;
685 { 614
686 }, 615 var boxY;
687 616 if (anchorTop > canvasHeight) {
688 /** 617 boxY = canvasHeight - titleHeight - arrowHeight;
689 * @param {!CanvasRenderingContext2D} context 618 renderArrowDown = true;
690 */ 619 } else if (anchorBottom < 0) {
691 _createCheckerboardPattern: function(context) 620 boxY = arrowHeight;
692 { 621 renderArrowUp = true;
693 var pattern = /** @type {!HTMLCanvasElement} */(createElement("canvas")) ; 622 } else if (anchorBottom + titleHeight + arrowHeight < canvasHeight) {
694 const size = 32; 623 boxY = anchorBottom + arrowHeight - 4;
695 pattern.width = size * 2; 624 renderArrowUp = true;
696 pattern.height = size * 2; 625 } else if (anchorTop - titleHeight - arrowHeight > 0) {
697 var pctx = pattern.getContext("2d"); 626 boxY = anchorTop - titleHeight - arrowHeight + 3;
698 627 renderArrowDown = true;
699 pctx.fillStyle = "rgb(195, 195, 195)"; 628 } else
700 pctx.fillRect(0, 0, size * 2, size * 2); 629 boxY = arrowHeight;
701 630
702 pctx.fillStyle = "rgb(225, 225, 225)"; 631 this._context.save();
703 pctx.fillRect(0, 0, size, size); 632 this._context.translate(0.5, 0.5);
704 pctx.fillRect(size, size, size, size); 633 this._context.beginPath();
705 return context.createPattern(pattern, "repeat"); 634 this._context.moveTo(boxX, boxY);
706 }, 635 if (renderArrowUp) {
707 636 this._context.lineTo(boxX + 2 * arrowHeight, boxY);
708 _createNavigationBar: function() 637 this._context.lineTo(boxX + 3 * arrowHeight, boxY - arrowHeight);
709 { 638 this._context.lineTo(boxX + 4 * arrowHeight, boxY);
710 this._navigationBar = this.element.createChild("div", "screencast-naviga tion"); 639 }
711 640 this._context.lineTo(boxX + titleWidth, boxY);
712 this._navigationBack = this._navigationBar.createChild("button", "back") ; 641 this._context.lineTo(boxX + titleWidth, boxY + titleHeight);
713 this._navigationBack.disabled = true; 642 if (renderArrowDown) {
714 this._navigationBack.addEventListener("click", this._navigateToHistoryEn try.bind(this, -1), false); 643 this._context.lineTo(boxX + 4 * arrowHeight, boxY + titleHeight);
715 644 this._context.lineTo(boxX + 3 * arrowHeight, boxY + titleHeight + arrowHei ght);
716 this._navigationForward = this._navigationBar.createChild("button", "for ward"); 645 this._context.lineTo(boxX + 2 * arrowHeight, boxY + titleHeight);
717 this._navigationForward.disabled = true; 646 }
718 this._navigationForward.addEventListener("click", this._navigateToHistor yEntry.bind(this, 1), false); 647 this._context.lineTo(boxX, boxY + titleHeight);
719 648 this._context.closePath();
720 this._navigationReload = this._navigationBar.createChild("button", "relo ad"); 649 this._context.fillStyle = 'rgb(255, 255, 194)';
721 this._navigationReload.addEventListener("click", this._navigateReload.bi nd(this), false); 650 this._context.fill();
722 651 this._context.strokeStyle = 'rgb(128, 128, 128)';
723 this._navigationUrl = this._navigationBar.createChild("input"); 652 this._context.stroke();
724 this._navigationUrl.type = "text"; 653
725 this._navigationUrl.addEventListener("keyup", this._navigationUrlKeyUp.b ind(this), true); 654 this._context.restore();
726 655
727 this._navigationProgressBar = new WebInspector.ScreencastView.ProgressTr acker(this._navigationBar.createChild("div", "progress")); 656 this._titleElement.style.top = (boxY + 3) + 'px';
728 657 this._titleElement.style.left = (boxX + 3) + 'px';
729 this._requestNavigationHistory(); 658 }
730 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.E vents.InspectedURLChanged, this._requestNavigationHistory, this); 659
731 }, 660 /**
732 661 * @return {!{width: number, height: number}}
733 _navigateToHistoryEntry: function(offset) 662 */
734 { 663 _viewportDimensions() {
735 var newIndex = this._historyIndex + offset; 664 const gutterSize = 30;
736 if (newIndex < 0 || newIndex >= this._historyEntries.length) 665 const bordersSize = WebInspector.ScreencastView._bordersSize;
737 return; 666 var width = this.element.offsetWidth - bordersSize - gutterSize;
738 this._target.pageAgent().navigateToHistoryEntry(this._historyEntries[new Index].id); 667 var height = this.element.offsetHeight - bordersSize - gutterSize - WebInspe ctor.ScreencastView._navBarHeight;
739 this._requestNavigationHistory(); 668 return {width: width, height: height};
740 }, 669 }
741 670
742 _navigateReload: function() 671 /**
743 { 672 * @override
744 this._resourceTreeModel.reloadPage(); 673 * @param {!DOMAgent.InspectMode} mode
745 }, 674 * @param {!DOMAgent.HighlightConfig} config
746 675 * @param {function(?Protocol.Error)=} callback
747 _navigationUrlKeyUp: function(event) 676 */
748 { 677 setInspectMode(mode, config, callback) {
749 if (event.key !== "Enter") 678 this._inspectModeConfig = mode !== DOMAgent.InspectMode.None ? config : null ;
750 return; 679 if (callback)
751 var url = this._navigationUrl.value; 680 callback(null);
752 if (!url) 681 }
753 return; 682
754 if (!url.match(WebInspector.ScreencastView._SchemeRegex)) 683 /**
755 url = "http://" + url; 684 * @override
756 this._target.pageAgent().navigate(url); 685 * @param {!PageAgent.FrameId} frameId
757 this._canvasElement.focus(); 686 */
758 }, 687 highlightFrame(frameId) {
759 688 }
760 _requestNavigationHistory: function() 689
761 { 690 /**
762 this._target.pageAgent().getNavigationHistory(this._onNavigationHistory. bind(this)); 691 * @param {!CanvasRenderingContext2D} context
763 }, 692 */
764 693 _createCheckerboardPattern(context) {
765 _onNavigationHistory: function(error, currentIndex, entries) 694 var pattern = /** @type {!HTMLCanvasElement} */ (createElement('canvas'));
766 { 695 const size = 32;
767 if (error) 696 pattern.width = size * 2;
768 return; 697 pattern.height = size * 2;
769 698 var pctx = pattern.getContext('2d');
770 this._historyIndex = currentIndex; 699
771 this._historyEntries = entries; 700 pctx.fillStyle = 'rgb(195, 195, 195)';
772 701 pctx.fillRect(0, 0, size * 2, size * 2);
773 this._navigationBack.disabled = currentIndex === 0; 702
774 this._navigationForward.disabled = currentIndex === (entries.length - 1) ; 703 pctx.fillStyle = 'rgb(225, 225, 225)';
775 704 pctx.fillRect(0, 0, size, size);
776 var url = entries[currentIndex].url; 705 pctx.fillRect(size, size, size, size);
777 var match = url.match(WebInspector.ScreencastView._HttpRegex); 706 return context.createPattern(pattern, 'repeat');
778 if (match) 707 }
779 url = match[1]; 708
780 InspectorFrontendHost.inspectedURLChanged(url); 709 _createNavigationBar() {
781 this._navigationUrl.value = url; 710 this._navigationBar = this.element.createChild('div', 'screencast-navigation ');
782 }, 711
783 712 this._navigationBack = this._navigationBar.createChild('button', 'back');
784 _focusNavigationBar: function() 713 this._navigationBack.disabled = true;
785 { 714 this._navigationBack.addEventListener('click', this._navigateToHistoryEntry. bind(this, -1), false);
786 this._navigationUrl.focus(); 715
787 this._navigationUrl.select(); 716 this._navigationForward = this._navigationBar.createChild('button', 'forward ');
788 return true; 717 this._navigationForward.disabled = true;
789 }, 718 this._navigationForward.addEventListener('click', this._navigateToHistoryEnt ry.bind(this, 1), false);
790 719
791 __proto__: WebInspector.VBox.prototype 720 this._navigationReload = this._navigationBar.createChild('button', 'reload') ;
721 this._navigationReload.addEventListener('click', this._navigateReload.bind(t his), false);
722
723 this._navigationUrl = this._navigationBar.createChild('input');
724 this._navigationUrl.type = 'text';
725 this._navigationUrl.addEventListener('keyup', this._navigationUrlKeyUp.bind( this), true);
726
727 this._navigationProgressBar =
728 new WebInspector.ScreencastView.ProgressTracker(this._navigationBar.crea teChild('div', 'progress'));
729
730 this._requestNavigationHistory();
731 WebInspector.targetManager.addEventListener(
732 WebInspector.TargetManager.Events.InspectedURLChanged, this._requestNavi gationHistory, this);
733 }
734
735 _navigateToHistoryEntry(offset) {
736 var newIndex = this._historyIndex + offset;
737 if (newIndex < 0 || newIndex >= this._historyEntries.length)
738 return;
739 this._target.pageAgent().navigateToHistoryEntry(this._historyEntries[newInde x].id);
740 this._requestNavigationHistory();
741 }
742
743 _navigateReload() {
744 this._resourceTreeModel.reloadPage();
745 }
746
747 _navigationUrlKeyUp(event) {
748 if (event.key !== 'Enter')
749 return;
750 var url = this._navigationUrl.value;
751 if (!url)
752 return;
753 if (!url.match(WebInspector.ScreencastView._SchemeRegex))
754 url = 'http://' + url;
755 this._target.pageAgent().navigate(url);
756 this._canvasElement.focus();
757 }
758
759 _requestNavigationHistory() {
760 this._target.pageAgent().getNavigationHistory(this._onNavigationHistory.bind (this));
761 }
762
763 _onNavigationHistory(error, currentIndex, entries) {
764 if (error)
765 return;
766
767 this._historyIndex = currentIndex;
768 this._historyEntries = entries;
769
770 this._navigationBack.disabled = currentIndex === 0;
771 this._navigationForward.disabled = currentIndex === (entries.length - 1);
772
773 var url = entries[currentIndex].url;
774 var match = url.match(WebInspector.ScreencastView._HttpRegex);
775 if (match)
776 url = match[1];
777 InspectorFrontendHost.inspectedURLChanged(url);
778 this._navigationUrl.value = url;
779 }
780
781 _focusNavigationBar() {
782 this._navigationUrl.focus();
783 this._navigationUrl.select();
784 return true;
785 }
792 }; 786 };
793 787
788 WebInspector.ScreencastView._bordersSize = 44;
789
790 WebInspector.ScreencastView._navBarHeight = 29;
791
792 WebInspector.ScreencastView._HttpRegex = /^http:\/\/(.+)/;
793
794 WebInspector.ScreencastView._SchemeRegex = /^(https?|about|chrome):/;
795
794 /** 796 /**
795 * @param {!Element} element 797 * @unrestricted
796 * @constructor
797 */ 798 */
798 WebInspector.ScreencastView.ProgressTracker = function(element) 799 WebInspector.ScreencastView.ProgressTracker = class {
799 { 800 /**
801 * @param {!Element} element
802 */
803 constructor(element) {
800 this._element = element; 804 this._element = element;
801 805
802 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.MainFrameNavigated, this._onMainFrameNavig ated, this); 806 WebInspector.targetManager.addModelListener(
803 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Load, this._onLoad, this); 807 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Ma inFrameNavigated,
804 WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, Web Inspector.NetworkManager.Events.RequestStarted, this._onRequestStarted, this); 808 this._onMainFrameNavigated, this);
805 WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, Web Inspector.NetworkManager.Events.RequestFinished, this._onRequestFinished, this); 809 WebInspector.targetManager.addModelListener(
810 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Lo ad, this._onLoad, this);
811 WebInspector.targetManager.addModelListener(
812 WebInspector.NetworkManager, WebInspector.NetworkManager.Events.RequestS tarted, this._onRequestStarted, this);
813 WebInspector.targetManager.addModelListener(
814 WebInspector.NetworkManager, WebInspector.NetworkManager.Events.RequestF inished, this._onRequestFinished, this);
815 }
816
817 _onMainFrameNavigated() {
818 this._requestIds = {};
819 this._startedRequests = 0;
820 this._finishedRequests = 0;
821 this._maxDisplayedProgress = 0;
822 this._updateProgress(0.1); // Display first 10% on navigation start.
823 }
824
825 _onLoad() {
826 delete this._requestIds;
827 this._updateProgress(1); // Display 100% progress on load, hide it in 0.5s.
828 setTimeout(function() {
829 if (!this._navigationProgressVisible())
830 this._displayProgress(0);
831 }.bind(this), 500);
832 }
833
834 _navigationProgressVisible() {
835 return !!this._requestIds;
836 }
837
838 _onRequestStarted(event) {
839 if (!this._navigationProgressVisible())
840 return;
841 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
842 // Ignore long-living WebSockets for the sake of progress indicator, as we w on't be waiting them anyway.
843 if (request.type === WebInspector.resourceTypes.WebSocket)
844 return;
845 this._requestIds[request.requestId] = request;
846 ++this._startedRequests;
847 }
848
849 _onRequestFinished(event) {
850 if (!this._navigationProgressVisible())
851 return;
852 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
853 if (!(request.requestId in this._requestIds))
854 return;
855 ++this._finishedRequests;
856 setTimeout(function() {
857 this._updateProgress(
858 this._finishedRequests / this._startedRequests * 0.9); // Finished re quests drive the progress up to 90%.
859 }.bind(this), 500); // Delay to give the new requests time to start. This m akes the progress smoother.
860 }
861
862 _updateProgress(progress) {
863 if (!this._navigationProgressVisible())
864 return;
865 if (this._maxDisplayedProgress >= progress)
866 return;
867 this._maxDisplayedProgress = progress;
868 this._displayProgress(progress);
869 }
870
871 _displayProgress(progress) {
872 this._element.style.width = (100 * progress) + '%';
873 }
806 }; 874 };
807
808 WebInspector.ScreencastView.ProgressTracker.prototype = {
809 _onMainFrameNavigated: function()
810 {
811 this._requestIds = {};
812 this._startedRequests = 0;
813 this._finishedRequests = 0;
814 this._maxDisplayedProgress = 0;
815 this._updateProgress(0.1); // Display first 10% on navigation start.
816 },
817
818 _onLoad: function()
819 {
820 delete this._requestIds;
821 this._updateProgress(1); // Display 100% progress on load, hide it in 0 .5s.
822 setTimeout(function() {
823 if (!this._navigationProgressVisible())
824 this._displayProgress(0);
825 }.bind(this), 500);
826 },
827
828 _navigationProgressVisible: function()
829 {
830 return !!this._requestIds;
831 },
832
833 _onRequestStarted: function(event)
834 {
835 if (!this._navigationProgressVisible())
836 return;
837 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
838 // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
839 if (request.type === WebInspector.resourceTypes.WebSocket)
840 return;
841 this._requestIds[request.requestId] = request;
842 ++this._startedRequests;
843 },
844
845 _onRequestFinished: function(event)
846 {
847 if (!this._navigationProgressVisible())
848 return;
849 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
850 if (!(request.requestId in this._requestIds))
851 return;
852 ++this._finishedRequests;
853 setTimeout(function() {
854 this._updateProgress(this._finishedRequests / this._startedRequests * 0.9); // Finished requests drive the progress up to 90%.
855 }.bind(this), 500); // Delay to give the new requests time to start. Th is makes the progress smoother.
856 },
857
858 _updateProgress: function(progress)
859 {
860 if (!this._navigationProgressVisible())
861 return;
862 if (this._maxDisplayedProgress >= progress)
863 return;
864 this._maxDisplayedProgress = progress;
865 this._displayProgress(progress);
866 },
867
868 _displayProgress: function(progress)
869 {
870 this._element.style.width = (100 * progress) + "%";
871 }
872 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698