OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @constructor | |
7 * @extends {WebInspector.VBox} | |
8 * @implements {WebInspector.OverridesSupport.PageResizer} | |
9 * @implements {WebInspector.TargetManager.Observer} | |
10 * @param {!WebInspector.InspectedPagePlaceholder} inspectedPagePlaceholder | |
11 */ | |
12 WebInspector.ResponsiveDesignView = function(inspectedPagePlaceholder) | |
13 { | |
14 WebInspector.VBox.call(this); | |
15 this.setMinimumSize(150, 150); | |
16 this.element.classList.add("responsive-design-view"); | |
17 this.registerRequiredCSS("emulation/responsiveDesignView.css"); | |
18 | |
19 this._showMediaQueryInspectorSetting = WebInspector.settings.createSetting("
showMediaQueryInspector", false); | |
20 | |
21 this._responsiveDesignContainer = new WebInspector.VBox(); | |
22 this._uiInitialized = false; | |
23 | |
24 this._inspectedPagePlaceholder = inspectedPagePlaceholder; | |
25 inspectedPagePlaceholder.show(this.element); | |
26 | |
27 this._enabled = false; | |
28 this._viewport = { scrollX: 0, scrollY: 0, contentsWidth: 0, contentsHeight:
0, pageScaleFactor: 1, minimumPageScaleFactor: 1, maximumPageScaleFactor: 1 }; | |
29 this._drawContentsSize = true; | |
30 this._deviceInsets = new Insets(0, 0, 0, 0); | |
31 this._pageContainerSrcset = ""; | |
32 this._viewportChangedThrottler = new WebInspector.Throttler(0); | |
33 this._pageScaleFactorThrottler = new WebInspector.Throttler(50); | |
34 | |
35 WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.Zo
omChanged, this._onZoomChanged, this); | |
36 WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport
.Events.EmulationStateChanged, this._emulationEnabledChanged, this); | |
37 WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Pag
e); | |
38 this._emulationEnabledChanged(); | |
39 }; | |
40 | |
41 // Measured in DIP. | |
42 WebInspector.ResponsiveDesignView.RulerWidth = 26; | |
43 WebInspector.ResponsiveDesignView.RulerHeight = 22; | |
44 WebInspector.ResponsiveDesignView.RulerTopHeight = 11; | |
45 WebInspector.ResponsiveDesignView.RulerBottomHeight = 9; | |
46 | |
47 WebInspector.ResponsiveDesignView.prototype = { | |
48 _ensureUIInitialized: function() | |
49 { | |
50 if (this._uiInitialized) | |
51 return; | |
52 | |
53 this._uiInitialized = true; | |
54 | |
55 this._createToolbar(); | |
56 | |
57 this._canvasContainer = new WebInspector.Widget(); | |
58 this._canvasContainer.element.classList.add("responsive-design"); | |
59 this._canvasContainer.show(this._responsiveDesignContainer.element); | |
60 | |
61 this._canvas = this._canvasContainer.element.createChild("canvas", "fill
responsive-design-canvas"); | |
62 | |
63 this._mediaInspectorContainer = this._canvasContainer.element.createChil
d("div", "responsive-design-media-container"); | |
64 WebInspector.Tooltip.addNativeOverrideContainer(this._mediaInspectorCont
ainer); | |
65 var deviceWidthSetting = WebInspector.overridesSupport.settings.deviceWi
dth; | |
66 this._mediaInspector = new WebInspector.MediaQueryInspector(deviceWidthS
etting.get.bind(deviceWidthSetting), deviceWidthSetting.set.bind(deviceWidthSett
ing)); | |
67 this._updateMediaQueryInspector(); | |
68 | |
69 WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSup
port.Events.OverridesWarningUpdated, this._overridesWarningUpdated, this); | |
70 | |
71 this._slidersContainer = this._canvasContainer.element.createChild("div"
, "vbox responsive-design-sliders-container"); | |
72 var genericDeviceOutline = this._slidersContainer.createChild("div", "re
sponsive-design-generic-outline-container"); | |
73 genericDeviceOutline.createChild("div", "responsive-design-generic-outli
ne"); | |
74 var widthSlider = this._slidersContainer.createChild("div", "responsive-
design-slider-width"); | |
75 widthSlider.createChild("div", "responsive-design-thumb-handle"); | |
76 this._createResizer(widthSlider, true, false); | |
77 var heightSlider = this._slidersContainer.createChild("div", "responsive
-design-slider-height"); | |
78 heightSlider.createChild("div", "responsive-design-thumb-handle"); | |
79 this._createResizer(heightSlider, false, true); | |
80 var cornerSlider = this._slidersContainer.createChild("div", "responsive
-design-slider-corner"); | |
81 this._createResizer(cornerSlider, true, true); | |
82 this._pageContainer = this._slidersContainer.createChild("div", "vbox fl
ex-auto responsive-design-page-container"); | |
83 this._pageContainerImage = this._pageContainer.createChild("img", "respo
nsive-design-page-container-image hidden"); | |
84 this._pageContainerImage.addEventListener("load", this._onPageContainerI
mageLoaded.bind(this, true), false); | |
85 this._pageContainerImage.addEventListener("error", this._onPageContainer
ImageLoaded.bind(this, false), false); | |
86 | |
87 // Page scale controls. | |
88 this._pageScaleContainer = this._canvasContainer.element.createChild("di
v", "hbox responsive-design-page-scale-container"); | |
89 this._decreasePageScaleButton = this._pageScaleContainer.createChild("bu
tton", "responsive-design-page-scale-button responsive-design-page-scale-decreas
e"); | |
90 this._decreasePageScaleButton.createChild("div", "glyph"); | |
91 this._decreasePageScaleButton.tabIndex = -1; | |
92 this._decreasePageScaleButton.addEventListener("click", this._pageScaleB
uttonClicked.bind(this, false), false); | |
93 | |
94 this._pageScaleLabel = this._pageScaleContainer.createChild("label", "re
sponsive-design-page-scale-label"); | |
95 this._pageScaleLabel.title = WebInspector.UIString("Shift + drag to chan
ge page scale"); | |
96 this._pageScaleLabel.addEventListener("dblclick", this._resetPageScale.b
ind(this), false); | |
97 | |
98 this._increasePageScaleButton = this._pageScaleContainer.createChild("bu
tton", "responsive-design-page-scale-button responsive-design-page-scale-increas
e"); | |
99 this._increasePageScaleButton.tabIndex = -1; | |
100 this._increasePageScaleButton.createChild("div", "glyph"); | |
101 this._increasePageScaleButton.addEventListener("click", this._pageScaleB
uttonClicked.bind(this, true), false); | |
102 | |
103 this._mediaInspector.addEventListener(WebInspector.MediaQueryInspector.E
vents.CountUpdated, this._updateMediaQueryInspectorButton, this); | |
104 this._overridesWarningUpdated(); | |
105 }, | |
106 | |
107 /** | |
108 * @override | |
109 * @param {!WebInspector.Target} target | |
110 */ | |
111 targetAdded: function(target) | |
112 { | |
113 if (this._target) | |
114 return; | |
115 this._target = target; | |
116 target.registerEmulationDispatcher(new WebInspector.EmulationDispatcher(
this)); | |
117 }, | |
118 | |
119 /** | |
120 * @override | |
121 * @param {!WebInspector.Target} target | |
122 */ | |
123 targetRemoved: function(target) | |
124 { | |
125 }, | |
126 | |
127 _invalidateCache: function() | |
128 { | |
129 delete this._cachedScale; | |
130 delete this._cachedCssCanvasWidth; | |
131 delete this._cachedCssCanvasHeight; | |
132 delete this._cachedCssHeight; | |
133 delete this._cachedCssWidth; | |
134 delete this._cachedCssPageWidth; | |
135 delete this._cachedCssPageHeight; | |
136 delete this._cachedDeviceInsets; | |
137 delete this._cachedZoomFactor; | |
138 delete this._cachedViewport; | |
139 delete this._cachedDrawContentsSize; | |
140 delete this._cachedMediaInspectorHeight; | |
141 delete this._availableSize; | |
142 }, | |
143 | |
144 _emulationEnabledChanged: function() | |
145 { | |
146 var enabled = WebInspector.overridesSupport.emulationEnabled(); | |
147 if (enabled && !this._enabled) { | |
148 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action
.DeviceModeEnabled); | |
149 this._invalidateCache(); | |
150 this._ignoreResize = true; | |
151 this._ensureUIInitialized(); | |
152 this._enabled = true; | |
153 this._mediaInspector.setEnabled(true); | |
154 this._inspectedPagePlaceholder.clearMinimumSizeAndMargins(); | |
155 this._inspectedPagePlaceholder.show(this._pageContainer); | |
156 this._responsiveDesignContainer.show(this.element); | |
157 delete this._ignoreResize; | |
158 this.onResize(); | |
159 } else if (!enabled && this._enabled) { | |
160 this._mediaInspector.setEnabled(false); | |
161 this._invalidateCache(); | |
162 this._ignoreResize = true; | |
163 this._enabled = false; | |
164 this._scale = 1; | |
165 this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins(); | |
166 this._responsiveDesignContainer.detach(); | |
167 this._inspectedPagePlaceholder.show(this.element); | |
168 delete this._ignoreResize; | |
169 this.onResize(); | |
170 } | |
171 }, | |
172 | |
173 /** | |
174 * @override | |
175 * WebInspector.OverridesSupport.PageResizer override. | |
176 * @param {number} dipWidth | |
177 * @param {number} dipHeight | |
178 * @param {number} scale | |
179 * @param {number} pageWidth | |
180 * @param {number} pageHeight | |
181 */ | |
182 update: function(dipWidth, dipHeight, scale, pageWidth, pageHeight) | |
183 { | |
184 this._scale = scale; | |
185 this._dipWidth = dipWidth ? Math.max(dipWidth, 1) : 0; | |
186 this._dipHeight = dipHeight ? Math.max(dipHeight, 1) : 0; | |
187 this._pageWidth = pageWidth ? Math.max(pageWidth, 1) : 0; | |
188 this._pageHeight = pageHeight ? Math.max(pageHeight, 1) : 0; | |
189 this._updateUI(); | |
190 }, | |
191 | |
192 updatePageResizer: function() | |
193 { | |
194 var available = this._availableDipSize(); | |
195 WebInspector.overridesSupport.setPageResizer(this, available.size, avail
able.insets); | |
196 }, | |
197 | |
198 /** | |
199 * @return {!{size: !Size, insets: !Insets}} | |
200 */ | |
201 _availableDipSize: function() | |
202 { | |
203 if (typeof this._availableSize === "undefined") { | |
204 if (!this._enabled) | |
205 return {size: new Size(1, 1), insets: new Insets(0, 0, 0, 0)}; | |
206 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
207 var rect = this._canvasContainer.element.getBoundingClientRect(); | |
208 var rulerTotalHeight = this._rulerTotalHeightDIP(); | |
209 this._availableSize = {size: new Size(Math.max(rect.width * zoomFact
or - WebInspector.ResponsiveDesignView.RulerWidth, 1), | |
210 Math.max(rect.height * zoomFac
tor - rulerTotalHeight, 1)), | |
211 insets: this._deviceInsets}; | |
212 } | |
213 return this._availableSize; | |
214 }, | |
215 | |
216 /** | |
217 * @param {!Element} element | |
218 * @param {boolean} x | |
219 * @param {boolean} y | |
220 * @return {!WebInspector.ResizerWidget} | |
221 */ | |
222 _createResizer: function(element, x, y) | |
223 { | |
224 var resizer = new WebInspector.ResizerWidget(); | |
225 resizer.addElement(element); | |
226 resizer.setCursor(x && y ? "nwse-resize" : (x ? "ew-resize" : "ns-resize
")); | |
227 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeStart,
this._onResizeStart, this); | |
228 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate,
this._onResizeUpdate.bind(this, x, y)); | |
229 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeEnd, th
is._onResizeEnd, this); | |
230 return resizer; | |
231 }, | |
232 | |
233 /** | |
234 * @param {!WebInspector.Event} event | |
235 */ | |
236 _onResizeStart: function(event) | |
237 { | |
238 this._drawContentsSize = false; | |
239 var available = this._availableDipSize().size; | |
240 this._slowPositionStart = null; | |
241 this._resizeStart = { x: this._dipWidth || available.width, y : this._di
pHeight || available.height }; | |
242 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.FixedScaleRequested, true); | |
243 this._updateUI(); | |
244 }, | |
245 | |
246 /** | |
247 * @param {boolean} x | |
248 * @param {boolean} y | |
249 * @param {!WebInspector.Event} event | |
250 */ | |
251 _onResizeUpdate: function(x, y, event) | |
252 { | |
253 if (event.data.shiftKey !== !!this._slowPositionStart) | |
254 this._slowPositionStart = event.data.shiftKey ? { x: event.data.curr
entX, y: event.data.currentY } : null; | |
255 | |
256 var cssOffsetX = event.data.currentX - event.data.startX; | |
257 var cssOffsetY = event.data.currentY - event.data.startY; | |
258 if (this._slowPositionStart) { | |
259 cssOffsetX = (event.data.currentX - this._slowPositionStart.x) / 10
+ this._slowPositionStart.x - event.data.startX; | |
260 cssOffsetY = (event.data.currentY - this._slowPositionStart.y) / 10
+ this._slowPositionStart.y - event.data.startY; | |
261 } | |
262 var dipOffsetX = Math.round(cssOffsetX * WebInspector.zoomManager.zoomFa
ctor()); | |
263 var dipOffsetY = Math.round(cssOffsetY * WebInspector.zoomManager.zoomFa
ctor()); | |
264 | |
265 var newSizeX = this._resizeStart.x + dipOffsetX; | |
266 newSizeX = Math.round(newSizeX / (this._scale || 1)); | |
267 newSizeX = Math.max(Math.min(newSizeX, WebInspector.OverridesSupport.Max
DeviceSize), 1); | |
268 var newSizeY = this._resizeStart.y + dipOffsetY; | |
269 newSizeY = Math.round(newSizeY / (this._scale || 1)); | |
270 newSizeY = Math.max(Math.min(newSizeY, WebInspector.OverridesSupport.Max
DeviceSize), 1); | |
271 | |
272 var requested = {}; | |
273 if (x) | |
274 requested.width = newSizeX; | |
275 if (y) | |
276 requested.height = newSizeY; | |
277 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.ResizeRequested, requested); | |
278 }, | |
279 | |
280 /** | |
281 * @param {!WebInspector.Event} event | |
282 */ | |
283 _onResizeEnd: function(event) | |
284 { | |
285 this._drawContentsSize = true; | |
286 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.FixedScaleRequested, false); | |
287 delete this._resizeStart; | |
288 this._updateUI(); | |
289 }, | |
290 | |
291 /** | |
292 * Draws canvas of the specified css size in DevTools page space. | |
293 * Canvas contains grid and rulers. | |
294 * @param {number} cssCanvasWidth | |
295 * @param {number} cssCanvasHeight | |
296 * @param {number} rulerHeight | |
297 */ | |
298 _drawCanvas: function(cssCanvasWidth, cssCanvasHeight, rulerHeight) | |
299 { | |
300 if (!this._enabled) | |
301 return; | |
302 | |
303 var canvas = this._canvas; | |
304 var context = canvas.getContext("2d"); | |
305 canvas.style.width = cssCanvasWidth + "px"; | |
306 canvas.style.height = cssCanvasHeight + "px"; | |
307 | |
308 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
309 var dipCanvasWidth = cssCanvasWidth * zoomFactor; | |
310 var dipCanvasHeight = cssCanvasHeight * zoomFactor; | |
311 | |
312 var deviceScaleFactor = window.devicePixelRatio; | |
313 canvas.width = deviceScaleFactor * cssCanvasWidth; | |
314 canvas.height = deviceScaleFactor * cssCanvasHeight; | |
315 context.scale(canvas.width / dipCanvasWidth, canvas.height / dipCanvasHe
ight); | |
316 context.font = "11px " + WebInspector.fontFamily(); | |
317 | |
318 const backgroundColor = "rgb(102, 102, 102)"; | |
319 const lightLineColor = "rgb(132, 132, 132)"; | |
320 const darkLineColor = "rgb(114, 114, 114)"; | |
321 const rulerColor = "rgb(125, 125, 125)"; | |
322 const textColor = "rgb(186, 186, 186)"; | |
323 const contentsSizeColor = "rgba(0, 0, 0, 0.3)"; | |
324 | |
325 var scale = (this._scale || 1) * this._viewport.pageScaleFactor; | |
326 var rulerScale = 0.5; | |
327 while (Math.abs(rulerScale * scale - 1) > Math.abs((rulerScale + 0.5) *
scale - 1)) | |
328 rulerScale += 0.5; | |
329 | |
330 var gridStep = 50 * scale * rulerScale; | |
331 var gridSubStep = 10 * scale * rulerScale; | |
332 | |
333 var rulerSubStep = 5 * scale * rulerScale; | |
334 var rulerStepCount = 20; | |
335 | |
336 var rulerWidth = WebInspector.ResponsiveDesignView.RulerWidth; | |
337 | |
338 var dipGridWidth = dipCanvasWidth - rulerWidth; | |
339 var dipGridHeight = dipCanvasHeight - rulerHeight; | |
340 var dipScrollX = this._viewport.scrollX * scale; | |
341 var dipScrollY = this._viewport.scrollY * scale; | |
342 context.translate(rulerWidth, rulerHeight); | |
343 | |
344 context.fillStyle = backgroundColor; | |
345 context.fillRect(0, 0, dipGridWidth, dipGridHeight); | |
346 | |
347 context.translate(0.5, 0.5); | |
348 context.strokeStyle = rulerColor; | |
349 context.fillStyle = textColor; | |
350 context.lineWidth = 1; | |
351 | |
352 // Draw horizontal ruler. | |
353 context.save(); | |
354 | |
355 var minXIndex = Math.ceil(dipScrollX / rulerSubStep); | |
356 var maxXIndex = Math.floor((dipScrollX + dipGridWidth) / rulerSubStep); | |
357 if (minXIndex) { | |
358 context.beginPath(); | |
359 context.moveTo(0, -rulerHeight); | |
360 context.lineTo(0, 0); | |
361 context.stroke(); | |
362 } | |
363 | |
364 context.translate(-dipScrollX, 0); | |
365 for (var index = minXIndex; index <= maxXIndex; index++) { | |
366 var x = index * rulerSubStep; | |
367 var height = WebInspector.ResponsiveDesignView.RulerHeight * 0.25; | |
368 | |
369 if (!(index % (rulerStepCount / 4))) | |
370 height = WebInspector.ResponsiveDesignView.RulerHeight * 0.5; | |
371 | |
372 if (!(index % (rulerStepCount / 2))) | |
373 height = rulerHeight; | |
374 | |
375 if (!(index % rulerStepCount)) { | |
376 context.save(); | |
377 context.translate(x, 0); | |
378 context.fillText(Math.round(x / scale), 2, -rulerHeight + 10); | |
379 context.restore(); | |
380 height = rulerHeight; | |
381 } | |
382 | |
383 context.beginPath(); | |
384 context.moveTo(x, - height); | |
385 context.lineTo(x, 0); | |
386 context.stroke(); | |
387 } | |
388 context.restore(); | |
389 | |
390 // Draw vertical ruler. | |
391 context.save(); | |
392 context.translate(0, this._deviceInsets.top); | |
393 var minYIndex = Math.ceil(dipScrollY / rulerSubStep); | |
394 var maxYIndex = Math.floor((dipScrollY + dipGridHeight) / rulerSubStep); | |
395 context.translate(0, -dipScrollY); | |
396 for (var index = minYIndex; index <= maxYIndex; index++) { | |
397 var y = index * rulerSubStep; | |
398 var x = -rulerWidth * 0.25; | |
399 if (!(index % (rulerStepCount / 4))) | |
400 x = -rulerWidth * 0.5; | |
401 if (!(index % (rulerStepCount / 2))) | |
402 x = -rulerWidth * 0.75; | |
403 | |
404 if (!(index % rulerStepCount)) { | |
405 context.save(); | |
406 context.translate(0, y); | |
407 context.rotate(-Math.PI / 2); | |
408 context.fillText(Math.round(y / scale), 2, -rulerWidth + 10); | |
409 context.restore(); | |
410 x = -rulerWidth; | |
411 } | |
412 | |
413 context.beginPath(); | |
414 context.moveTo(x, y); | |
415 context.lineTo(0, y); | |
416 context.stroke(); | |
417 } | |
418 context.restore(); | |
419 | |
420 // Draw grid. | |
421 drawGrid(dipScrollX, dipScrollY + this._deviceInsets.top, darkLineColor,
gridSubStep); | |
422 drawGrid(dipScrollX, dipScrollY + this._deviceInsets.top, lightLineColor
, gridStep); | |
423 | |
424 /** | |
425 * @param {number} scrollX | |
426 * @param {number} scrollY | |
427 * @param {string} color | |
428 * @param {number} step | |
429 */ | |
430 function drawGrid(scrollX, scrollY, color, step) | |
431 { | |
432 context.strokeStyle = color; | |
433 var minX = Math.ceil(scrollX / step) * step; | |
434 var maxX = Math.floor((scrollX + dipGridWidth) / step) * step - minX
; | |
435 var minY = Math.ceil(scrollY / step) * step; | |
436 var maxY = Math.floor((scrollY + dipGridHeight) / step) * step - min
Y; | |
437 | |
438 context.save(); | |
439 context.translate(minX - scrollX, 0); | |
440 for (var x = 0; x <= maxX; x += step) { | |
441 context.beginPath(); | |
442 context.moveTo(x, 0); | |
443 context.lineTo(x, dipGridHeight); | |
444 context.stroke(); | |
445 } | |
446 context.restore(); | |
447 | |
448 context.save(); | |
449 context.translate(0, minY - scrollY); | |
450 for (var y = 0; y <= maxY; y += step) { | |
451 context.beginPath(); | |
452 context.moveTo(0, y); | |
453 context.lineTo(dipGridWidth, y); | |
454 context.stroke(); | |
455 } | |
456 context.restore(); | |
457 } | |
458 | |
459 context.translate(-0.5, -0.5); | |
460 | |
461 // Draw contents size. | |
462 var pageScaleAvailable = WebInspector.overridesSupport.settings.emulateM
obile.get() || WebInspector.overridesSupport.settings.emulateTouch.get(); | |
463 if (this._drawContentsSize && pageScaleAvailable) { | |
464 context.save(); | |
465 context.fillStyle = contentsSizeColor; | |
466 var visibleContentsWidth = Math.max(0, Math.min(dipGridWidth, this._
viewport.contentsWidth * scale - dipScrollX)); | |
467 var visibleContentsHeight = Math.max(0, Math.min(dipGridHeight, this
._viewport.contentsHeight * scale - dipScrollY + this._deviceInsets.top)); | |
468 context.translate(0, this._deviceInsets.top); | |
469 context.fillRect(0, Math.max(-this._deviceInsets.top, -dipScrollY),
visibleContentsWidth, visibleContentsHeight); | |
470 context.restore(); | |
471 } | |
472 }, | |
473 | |
474 /** | |
475 * @return {number} | |
476 */ | |
477 _rulerTotalHeightDIP: function() | |
478 { | |
479 var mediaInspectorHeight = this._mediaInspector.isShowing() ? this._medi
aInspector.element.offsetHeight : 0; | |
480 if (!mediaInspectorHeight) | |
481 return WebInspector.ResponsiveDesignView.RulerHeight; | |
482 return WebInspector.ResponsiveDesignView.RulerTopHeight + WebInspector.R
esponsiveDesignView.RulerBottomHeight + mediaInspectorHeight * WebInspector.zoom
Manager.zoomFactor(); | |
483 }, | |
484 | |
485 _updateUI: function() | |
486 { | |
487 if (!this._enabled || !this.isShowing()) | |
488 return; | |
489 | |
490 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
491 var rect = this._canvas.parentElement.getBoundingClientRect(); | |
492 var availableDip = this._availableDipSize().size; | |
493 var cssCanvasWidth = rect.width; | |
494 var cssCanvasHeight = rect.height; | |
495 var mediaInspectorHeight = this._mediaInspector.isShowing() ? this._medi
aInspector.element.offsetHeight : 0; | |
496 var rulerTotalHeight = this._rulerTotalHeightDIP(); | |
497 | |
498 this._mediaInspector.setAxisTransform(this._viewport.scrollX, this._scal
e * this._viewport.pageScaleFactor); | |
499 | |
500 if (this._cachedZoomFactor !== zoomFactor || this._cachedMediaInspectorH
eight !== mediaInspectorHeight) { | |
501 var cssRulerWidth = WebInspector.ResponsiveDesignView.RulerWidth / z
oomFactor + "px"; | |
502 var cssRulerHeight = (mediaInspectorHeight ? WebInspector.Responsive
DesignView.RulerTopHeight : WebInspector.ResponsiveDesignView.RulerHeight) / zoo
mFactor + "px"; | |
503 var cssCanvasOffset = rulerTotalHeight / zoomFactor + "px"; | |
504 this._slidersContainer.style.left = cssRulerWidth; | |
505 this._slidersContainer.style.top = cssCanvasOffset; | |
506 this._warningInfobar.element.style.height = cssCanvasOffset; | |
507 this._pageScaleContainer.style.top = cssCanvasOffset; | |
508 this._mediaInspectorContainer.style.left = cssRulerWidth; | |
509 this._mediaInspectorContainer.style.marginTop = cssRulerHeight; | |
510 this._warningInfobar.element.style.left = cssRulerWidth; | |
511 } | |
512 | |
513 var cssWidth = (this._dipWidth ? this._dipWidth : availableDip.width) /
zoomFactor; | |
514 var cssHeight = (this._dipHeight ? this._dipHeight : availableDip.height
) / zoomFactor; | |
515 var cssPageWidth = (this._pageWidth ? this._pageWidth : availableDip.wid
th) / zoomFactor; | |
516 var cssPageHeight = (this._pageHeight ? this._pageHeight : availableDip.
height) / zoomFactor; | |
517 var deviceInsets = new Insets(this._deviceInsets.left * this._scale / zo
omFactor, this._deviceInsets.top * this._scale / zoomFactor, this._deviceInsets.
right * this._scale / zoomFactor, this._deviceInsets.bottom * this._scale / zoom
Factor); | |
518 cssWidth += deviceInsets.left + deviceInsets.right; | |
519 cssHeight += deviceInsets.top + deviceInsets.bottom; | |
520 var insetsChanged = !deviceInsets.isEqual(this._cachedDeviceInsets); | |
521 if (this._cachedCssWidth !== cssWidth || this._cachedCssHeight !== cssHe
ight || insetsChanged) { | |
522 this._slidersContainer.style.width = cssWidth + "px"; | |
523 this._slidersContainer.style.height = cssHeight + "px"; | |
524 this._pageContainer.style.paddingLeft = deviceInsets.left + "px"; | |
525 this._pageContainer.style.paddingTop = deviceInsets.top + "px"; | |
526 this._pageContainer.style.paddingRight = deviceInsets.right + "px"; | |
527 this._pageContainer.style.paddingBottom = deviceInsets.bottom + "px"
; | |
528 this._inspectedPagePlaceholder.onResize(); | |
529 } | |
530 | |
531 if (this._cachedCssPageWidth !== cssPageWidth || this._cachedCssPageHeig
ht !== cssPageHeight) { | |
532 this._pageContainerImage.style.width = cssPageWidth + "px"; | |
533 this._pageContainerImage.style.height = cssPageHeight + "px"; | |
534 } | |
535 | |
536 this._loadPageContainerImage(); | |
537 | |
538 var pageScaleVisible = cssWidth + this._pageScaleContainerWidth + WebIns
pector.ResponsiveDesignView.RulerWidth / zoomFactor <= rect.width; | |
539 this._pageScaleContainer.classList.toggle("hidden", !pageScaleVisible); | |
540 | |
541 var viewportChanged = !this._cachedViewport | |
542 || this._cachedViewport.scrollX !== this._viewport.scrollX || this._
cachedViewport.scrollY !== this._viewport.scrollY | |
543 || this._cachedViewport.contentsWidth !== this._viewport.contentsWid
th || this._cachedViewport.contentsHeight !== this._viewport.contentsHeight | |
544 || this._cachedViewport.pageScaleFactor !== this._viewport.pageScale
Factor | |
545 || this._cachedViewport.minimumPageScaleFactor !== this._viewport.mi
nimumPageScaleFactor | |
546 || this._cachedViewport.maximumPageScaleFactor !== this._viewport.ma
ximumPageScaleFactor; | |
547 | |
548 var canvasInvalidated = viewportChanged || this._drawContentsSize !== th
is._cachedDrawContentsSize || this._cachedScale !== this._scale || | |
549 this._cachedCssCanvasWidth !== cssCanvasWidth || this._cachedCssCanv
asHeight !== cssCanvasHeight || this._cachedZoomFactor !== zoomFactor || | |
550 this._cachedMediaInspectorHeight !== mediaInspectorHeight || insetsC
hanged; | |
551 | |
552 if (canvasInvalidated) | |
553 this._drawCanvas(cssCanvasWidth, cssCanvasHeight, rulerTotalHeight); | |
554 | |
555 if (viewportChanged) { | |
556 this._pageScaleLabel.textContent = WebInspector.UIString("%.1f", thi
s._viewport.pageScaleFactor); | |
557 this._decreasePageScaleButton.title = WebInspector.UIString("Scale d
own (minimum %.1f)", this._viewport.minimumPageScaleFactor); | |
558 this._decreasePageScaleButton.disabled = this._viewport.pageScaleFac
tor <= this._viewport.minimumPageScaleFactor; | |
559 this._increasePageScaleButton.title = WebInspector.UIString("Scale u
p (maximum %.1f)", this._viewport.maximumPageScaleFactor); | |
560 this._increasePageScaleButton.disabled = this._viewport.pageScaleFac
tor >= this._viewport.maximumPageScaleFactor; | |
561 } | |
562 | |
563 this._cachedScale = this._scale; | |
564 this._cachedCssCanvasWidth = cssCanvasWidth; | |
565 this._cachedCssCanvasHeight = cssCanvasHeight; | |
566 this._cachedCssHeight = cssHeight; | |
567 this._cachedCssWidth = cssWidth; | |
568 this._cachedCssPageWidth = cssPageWidth; | |
569 this._cachedCssPageHeight = cssPageHeight; | |
570 this._cachedDeviceInsets = deviceInsets; | |
571 this._cachedZoomFactor = zoomFactor; | |
572 this._cachedViewport = this._viewport; | |
573 this._cachedDrawContentsSize = this._drawContentsSize; | |
574 this._cachedMediaInspectorHeight = mediaInspectorHeight; | |
575 }, | |
576 | |
577 _loadPageContainerImage: function() | |
578 { | |
579 if (this._pageContainerImage.getAttribute("srcset") === this._pageContai
nerSrcset) | |
580 return; | |
581 this._pageContainerImage.setAttribute("srcset", this._pageContainerSrcse
t); | |
582 if (!this._pageContainerSrcset) | |
583 this._pageContainerImage.classList.toggle("hidden", true); | |
584 }, | |
585 | |
586 /** | |
587 * @param {boolean} success | |
588 */ | |
589 _onPageContainerImageLoaded: function(success) | |
590 { | |
591 this._pageContainerImage.classList.toggle("hidden", !success); | |
592 }, | |
593 | |
594 onResize: function() | |
595 { | |
596 if (!this._enabled || this._ignoreResize) | |
597 return; | |
598 var oldSize = this._availableSize; | |
599 | |
600 this._pageScaleContainer.classList.remove("hidden"); | |
601 this._pageScaleContainerWidth = this._pageScaleContainer.offsetWidth; | |
602 | |
603 delete this._availableSize; | |
604 var newSize = this._availableDipSize(); | |
605 if (!oldSize || !newSize.size.isEqual(oldSize.size) || !newSize.insets.i
sEqual(oldSize.insets)) | |
606 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResi
zer.Events.AvailableSizeChanged, newSize); | |
607 this._updateUI(); | |
608 this._inspectedPagePlaceholder.onResize(); | |
609 }, | |
610 | |
611 _onZoomChanged: function() | |
612 { | |
613 this._updateUI(); | |
614 }, | |
615 | |
616 _createToolbar: function() | |
617 { | |
618 this._toolbarElement = this._responsiveDesignContainer.element.createChi
ld("div", "responsive-design-toolbar"); | |
619 this._createButtonsSection(); | |
620 this._createDeviceSection(); | |
621 this._toolbarElement.createChild("div", "responsive-design-separator"); | |
622 this._createNetworkSection(); | |
623 this._toolbarElement.createChild("div", "responsive-design-separator"); | |
624 | |
625 var moreButtonContainer = this._toolbarElement.createChild("div", "respo
nsive-design-more-button-container"); | |
626 var moreButton = moreButtonContainer.createChild("button", "responsive-d
esign-more-button"); | |
627 moreButton.title = WebInspector.UIString("More overrides"); | |
628 moreButton.addEventListener("click", this._showEmulationInDrawer.bind(th
is), false); | |
629 moreButton.textContent = "\u2026"; | |
630 }, | |
631 | |
632 _createButtonsSection: function() | |
633 { | |
634 var buttonsToolbar = new WebInspector.Toolbar("", this._toolbarElement); | |
635 buttonsToolbar.makeVertical(); | |
636 buttonsToolbar.setColor("white"); | |
637 buttonsToolbar.setToggledColor("rgb(105, 194, 236)"); | |
638 buttonsToolbar.element.classList.add("responsive-design-section", "respo
nsive-design-section-buttons"); | |
639 | |
640 var resetButton = new WebInspector.ToolbarButton(WebInspector.UIString("
Reset all overrides"), "clear-toolbar-item"); | |
641 buttonsToolbar.appendToolbarItem(resetButton); | |
642 resetButton.addEventListener("click", WebInspector.overridesSupport.rese
t, WebInspector.overridesSupport); | |
643 | |
644 // Media Query Inspector. | |
645 this._toggleMediaInspectorButton = new WebInspector.ToolbarToggle(WebIns
pector.UIString("Media queries not found"), "waterfall-toolbar-item"); | |
646 this._toggleMediaInspectorButton.setToggled(this._showMediaQueryInspecto
rSetting.get()); | |
647 this._toggleMediaInspectorButton.setEnabled(false); | |
648 this._toggleMediaInspectorButton.addEventListener("click", this._onToggl
eMediaInspectorButtonClick, this); | |
649 this._showMediaQueryInspectorSetting.addChangeListener(this._updateMedia
QueryInspector, this); | |
650 buttonsToolbar.appendToolbarItem(this._toggleMediaInspectorButton); | |
651 }, | |
652 | |
653 _createDeviceSection: function() | |
654 { | |
655 var deviceSection = this._toolbarElement.createChild("div", "responsive-
design-section responsive-design-section-device"); | |
656 deviceSection.createChild("div", "responsive-design-section-decorator"); | |
657 | |
658 // Device. | |
659 var deviceElement = deviceSection.createChild("div", "responsive-design-
suite responsive-design-suite-top").createChild("div"); | |
660 | |
661 var fieldsetElement = deviceElement.createChild("fieldset"); | |
662 fieldsetElement.createChild("label").textContent = WebInspector.UIString
("Device"); | |
663 var deviceSelect = new WebInspector.DeviceSelect(createElementWithClass(
"button", "responsive-design-icon responsive-design-icon-swap"), this._deviceMod
eSelected.bind(this)); | |
664 fieldsetElement.appendChild(deviceSelect.element); | |
665 deviceSelect.element.classList.add("responsive-design-device-select"); | |
666 | |
667 var detailsElement = deviceSection.createChild("div", "responsive-design
-suite"); | |
668 | |
669 // Dimensions. | |
670 var screenElement = detailsElement.createChild("div", ""); | |
671 fieldsetElement = screenElement.createChild("fieldset"); | |
672 | |
673 var emulateResolutionCheckbox = WebInspector.SettingsUI.createSettingChe
ckbox("", WebInspector.overridesSupport.settings.emulateResolution, true, WebIns
pector.UIString("Emulate screen resolution")); | |
674 themeCheckbox(emulateResolutionCheckbox); | |
675 fieldsetElement.appendChild(emulateResolutionCheckbox); | |
676 | |
677 fieldsetElement.createChild("label").textContent = WebInspector.UIString
("Screen"); | |
678 var resolutionFieldset = WebInspector.SettingsUI.createSettingFieldset(W
ebInspector.overridesSupport.settings.emulateResolution); | |
679 fieldsetElement.appendChild(resolutionFieldset); | |
680 | |
681 resolutionFieldset.appendChild(WebInspector.SettingsUI.createSettingInpu
tField("", WebInspector.overridesSupport.settings.deviceWidth, true, 4, "3em", W
ebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UIStr
ing("\u2013"))); | |
682 resolutionFieldset.createTextChild("\u00D7"); | |
683 resolutionFieldset.appendChild(WebInspector.SettingsUI.createSettingInpu
tField("", WebInspector.overridesSupport.settings.deviceHeight, true, 4, "3em",
WebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UISt
ring("\u2013"))); | |
684 | |
685 // Device pixel ratio. | |
686 detailsElement.createChild("div", "responsive-design-suite-separator"); | |
687 | |
688 var dprElement = detailsElement.createChild("div", ""); | |
689 var resolutionFieldset2 = WebInspector.SettingsUI.createSettingFieldset(
WebInspector.overridesSupport.settings.emulateResolution); | |
690 dprElement.appendChild(resolutionFieldset2); | |
691 var dprButton = resolutionFieldset2.createChild("div", "responsive-desig
n-icon responsive-design-icon-dpr"); | |
692 dprButton.title = WebInspector.UIString("Device pixel ratio"); | |
693 resolutionFieldset2.appendChild(WebInspector.SettingsUI.createSettingInp
utField("", WebInspector.overridesSupport.settings.deviceScaleFactor, true, 4, "
1.9em", WebInspector.OverridesSupport.deviceScaleFactorValidator, true, true, We
bInspector.UIString("\u2013"))); | |
694 | |
695 // Fit to window. | |
696 detailsElement.createChild("div", "responsive-design-suite-separator"); | |
697 var fitToWindowElement = detailsElement.createChild("div", ""); | |
698 fieldsetElement = fitToWindowElement.createChild("fieldset"); | |
699 var fitCheckbox = WebInspector.SettingsUI.createSettingCheckbox(WebInspe
ctor.UIString("Zoom to fit"), WebInspector.overridesSupport.settings.deviceFitWi
ndow, true, WebInspector.UIString("Zoom to fit available space")) | |
700 fieldsetElement.appendChild(fitCheckbox); | |
701 themeCheckbox(fitCheckbox); | |
702 | |
703 /** | |
704 * @param {!Element} checkbox | |
705 */ | |
706 function themeCheckbox(checkbox) | |
707 { | |
708 checkbox.checkColor = "rgb(255, 156, 0)"; | |
709 checkbox.backgroundColor = "rgb(102, 102, 102)"; | |
710 checkbox.borderColor = "rgb(45, 45, 45)"; | |
711 } | |
712 }, | |
713 | |
714 _createNetworkSection: function() | |
715 { | |
716 var networkSection = this._toolbarElement.createChild("div", "responsive
-design-section responsive-design-section-network"); | |
717 networkSection.createChild("div", "responsive-design-section-decorator")
; | |
718 | |
719 var networkLabel = networkSection.createChild("div", "responsive-design-
suite responsive-design-suite-top").createChild("div").createChild("label"); | |
720 networkLabel.textContent = WebInspector.UIString("Network"); | |
721 | |
722 var showDrawerButton = networkSection.createChild("div", "responsive-des
ign-suite").createChild("a"); | |
723 showDrawerButton.textContent = WebInspector.UIString("Configure throttli
ng"); | |
724 var action = WebInspector.actionRegistry.action("network.show-config"); | |
725 showDrawerButton.addEventListener("click", action.execute.bind(action)); | |
726 }, | |
727 | |
728 _onToggleMediaInspectorButtonClick: function() | |
729 { | |
730 this._showMediaQueryInspectorSetting.set(!this._toggleMediaInspectorButt
on.toggled()); | |
731 }, | |
732 | |
733 _updateMediaQueryInspector: function() | |
734 { | |
735 this._toggleMediaInspectorButton.setToggled(this._showMediaQueryInspecto
rSetting.get()); | |
736 if (this._mediaInspector.isShowing() === this._showMediaQueryInspectorSe
tting.get()) | |
737 return; | |
738 if (this._mediaInspector.isShowing()) | |
739 this._mediaInspector.detach(); | |
740 else | |
741 this._mediaInspector.show(this._mediaInspectorContainer); | |
742 this.onResize(); | |
743 }, | |
744 | |
745 /** | |
746 * @param {!WebInspector.Event} event | |
747 */ | |
748 _updateMediaQueryInspectorButton: function(event) | |
749 { | |
750 var count = /** @type {number} */ (event.data); | |
751 this._toggleMediaInspectorButton.setEnabled(!!count); | |
752 this._toggleMediaInspectorButton.setTitle(!count ? WebInspector.UIString
("Media queries not found") : | |
753 WebInspector.UIString((count === 1 ? "%d media query found" : "%d me
dia queries found"), count)); | |
754 }, | |
755 | |
756 _overridesWarningUpdated: function() | |
757 { | |
758 var message = WebInspector.overridesSupport.warningMessage(); | |
759 if (!message) { | |
760 if (this._warningInfobar) { | |
761 this._warningInfobar.dispose(); | |
762 delete this._warningInfobar; | |
763 } | |
764 } | |
765 | |
766 if (!this._warningInfobar) { | |
767 this._warningInfobar = WebInspector.Infobar.create(WebInspector.Info
bar.Type.Warning, message, WebInspector.moduleSetting("disableOverridesWarning")
); | |
768 if (this._warningInfobar) { | |
769 this._warningInfobar.element.classList.add("responsive-design-wa
rning"); | |
770 this._warningInfobar.setCloseCallback(WebInspector.overridesSupp
ort.clearWarningMessage.bind(WebInspector.overridesSupport)); | |
771 this._canvasContainer.element.appendChild(this._warningInfobar.e
lement); | |
772 } | |
773 } else { | |
774 this._warningInfobar.setText(message); | |
775 } | |
776 }, | |
777 | |
778 _showEmulationInDrawer: function() | |
779 { | |
780 WebInspector.Revealer.reveal(WebInspector.overridesSupport); | |
781 }, | |
782 | |
783 /** | |
784 * @param {?WebInspector.EmulatedDevice} device | |
785 * @param {?WebInspector.EmulatedDevice.Mode} mode | |
786 */ | |
787 _deviceModeSelected: function(device, mode) | |
788 { | |
789 this._pageContainerSrcset = ""; | |
790 if (device && mode) { | |
791 var orientation = device.orientationByName(mode.orientation); | |
792 this._deviceInsets = mode.insets; | |
793 WebInspector.overridesSupport.settings.screenOrientationOverride.set
(mode.orientation == WebInspector.EmulatedDevice.Horizontal ? "landscapePrimary"
: "portraitPrimary"); | |
794 this._pageContainerSrcset = device.modeImage(mode); | |
795 } else { | |
796 this._deviceInsets = new Insets(0, 0, 0, 0); | |
797 WebInspector.overridesSupport.settings.screenOrientationOverride.set
(""); | |
798 } | |
799 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.InsetsChanged, this._deviceInsets); | |
800 }, | |
801 | |
802 /** | |
803 * @param {!EmulationAgent.Viewport=} viewport | |
804 */ | |
805 _viewportChanged: function(viewport) | |
806 { | |
807 if (viewport) { | |
808 this._viewport = viewport; | |
809 this._viewport.minimumPageScaleFactor = Math.max(0.1, this._viewport
.minimumPageScaleFactor); | |
810 this._viewport.minimumPageScaleFactor = Math.min(this._viewport.mini
mumPageScaleFactor, this._viewport.pageScaleFactor); | |
811 this._viewport.maximumPageScaleFactor = Math.min(10, this._viewport.
maximumPageScaleFactor); | |
812 this._viewport.maximumPageScaleFactor = Math.max(this._viewport.maxi
mumPageScaleFactor, this._viewport.pageScaleFactor); | |
813 this._viewportChangedThrottler.schedule(this._updateUIThrottled.bind
(this)); | |
814 } | |
815 }, | |
816 | |
817 /** | |
818 * @return {!Promise.<?>} | |
819 */ | |
820 _updateUIThrottled: function() | |
821 { | |
822 this._updateUI(); | |
823 return Promise.resolve(); | |
824 }, | |
825 | |
826 /** | |
827 * @param {boolean} increase | |
828 * @param {!Event} event | |
829 */ | |
830 _pageScaleButtonClicked: function(increase, event) | |
831 { | |
832 this._pageScaleFactorThrottler.schedule(updatePageScaleFactor.bind(this)
); | |
833 | |
834 /** | |
835 * @return {!Promise.<?>} | |
836 * @this {WebInspector.ResponsiveDesignView} | |
837 */ | |
838 function updatePageScaleFactor() | |
839 { | |
840 if (this._target && this._viewport) { | |
841 var value = this._viewport.pageScaleFactor; | |
842 value = increase ? value * 1.1 : value / 1.1; | |
843 value = Math.min(this._viewport.maximumPageScaleFactor, value); | |
844 value = Math.max(this._viewport.minimumPageScaleFactor, value); | |
845 this._target.emulationAgent().setPageScaleFactor(value); | |
846 } | |
847 return Promise.resolve(); | |
848 } | |
849 }, | |
850 | |
851 _resetPageScale: function() | |
852 { | |
853 this._pageScaleFactorThrottler.schedule(updatePageScaleFactor.bind(this)
); | |
854 | |
855 /** | |
856 * @return {!Promise.<?>} | |
857 * @this {WebInspector.ResponsiveDesignView} | |
858 */ | |
859 function updatePageScaleFactor() | |
860 { | |
861 if (this._target && this._viewport && this._viewport.minimumPageScal
eFactor <= 1 && this._viewport.maximumPageScaleFactor >= 1) | |
862 this._target.emulationAgent().setPageScaleFactor(1); | |
863 return Promise.resolve(); | |
864 } | |
865 }, | |
866 | |
867 __proto__: WebInspector.VBox.prototype | |
868 }; | |
869 | |
870 | |
871 /** | |
872 * @constructor | |
873 * @implements {EmulationAgent.Dispatcher} | |
874 * @param {!WebInspector.ResponsiveDesignView} responsiveDesignView | |
875 */ | |
876 WebInspector.EmulationDispatcher = function(responsiveDesignView) | |
877 { | |
878 this._responsiveDesignView = responsiveDesignView; | |
879 } | |
880 | |
881 WebInspector.EmulationDispatcher.prototype = { | |
882 /** | |
883 * @override | |
884 * @param {!EmulationAgent.Viewport=} viewport | |
885 */ | |
886 viewportChanged: function(viewport) | |
887 { | |
888 this._responsiveDesignView._viewportChanged(viewport); | |
889 } | |
890 } | |
OLD | NEW |