Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / toolbox / ResponsiveDesignView.js
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("overflow-hidden");
17
18     this._responsiveDesignContainer = new WebInspector.VBox();
19     this._responsiveDesignContainer.registerRequiredCSS("responsiveDesignView.css");
20
21     this._createToolbar();
22
23     this._mediaInspector = new WebInspector.MediaQueryInspector();
24     this._mediaInspectorContainer = this._responsiveDesignContainer.element.createChild("div", "responsive-design-media-container");
25     this._updateMediaQueryInspector();
26
27     this._canvasContainer = new WebInspector.View();
28     this._canvasContainer.element.classList.add("responsive-design");
29     this._canvasContainer.show(this._responsiveDesignContainer.element);
30
31     this._canvas = this._canvasContainer.element.createChild("canvas", "fill");
32
33     this._rulerGlasspane = this._canvasContainer.element.createChild("div", "responsive-design-ruler-glasspane");
34     this._rulerGlasspane.appendChild(this._mediaInspector.rulerDecorationLayer());
35
36     this._warningMessage = this._canvasContainer.element.createChild("div", "responsive-design-warning hidden");
37     this._warningMessage.createChild("div", "warning-icon-small");
38     this._warningMessage.createChild("span");
39     var warningCloseButton = this._warningMessage.createChild("div", "close-button");
40     warningCloseButton.addEventListener("click", WebInspector.overridesSupport.clearWarningMessage.bind(WebInspector.overridesSupport), false);
41     WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport.Events.OverridesWarningUpdated, this._overridesWarningUpdated, this);
42
43     this._slidersContainer = this._canvasContainer.element.createChild("div", "vbox responsive-design-sliders-container");
44     var hbox = this._slidersContainer.createChild("div", "hbox flex-auto");
45     this._heightSliderContainer = this._slidersContainer.createChild("div", "hbox responsive-design-slider-height");
46     this._pageContainer = hbox.createChild("div", "vbox flex-auto");
47     this._widthSliderContainer = hbox.createChild("div", "vbox responsive-design-slider-width");
48
49     this._widthSlider = this._widthSliderContainer.createChild("div", "responsive-design-slider-thumb");
50     this._widthSlider.createChild("div", "responsive-design-thumb-handle");
51     this._createResizer(this._widthSlider, false);
52     this._heightSlider = this._heightSliderContainer.createChild("div", "responsive-design-slider-thumb");
53     this._heightSlider.createChild("div", "responsive-design-thumb-handle");
54     this._createResizer(this._heightSlider, true);
55
56     this._inspectedPagePlaceholder = inspectedPagePlaceholder;
57     inspectedPagePlaceholder.show(this.element);
58
59     this._enabled = false;
60     this._viewport = { scrollX: 0, scrollY: 0, contentsWidth: 0, contentsHeight: 0, pageScaleFactor: 1 };
61     this._drawContentsSize = true;
62     this._viewportChangedThrottler = new WebInspector.Throttler(0);
63
64     WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.ZoomChanged, this._onZoomChanged, this);
65     WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport.Events.EmulationStateChanged, this._emulationEnabledChanged, this);
66     this._mediaInspector.addEventListener(WebInspector.MediaQueryInspector.Events.HeightUpdated, this.onResize, this);
67     WebInspector.targetManager.observeTargets(this);
68
69     this._emulationEnabledChanged();
70     this._overridesWarningUpdated();
71 };
72
73 // Measured in DIP.
74 WebInspector.ResponsiveDesignView.SliderWidth = 19;
75 WebInspector.ResponsiveDesignView.RulerWidth = 22;
76
77 WebInspector.ResponsiveDesignView.prototype = {
78
79     /**
80      * @param {!WebInspector.Target} target
81      */
82     targetAdded: function(target)
83     {
84         // FIXME: adapt this to multiple targets.
85         if (this._target)
86             return;
87         this._target = target;
88         target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ViewportChanged, this._viewportChanged, this);
89     },
90
91     /**
92      * @param {!WebInspector.Target} target
93      */
94     targetRemoved: function(target)
95     {
96         if (target !== this._target)
97             return;
98         target.resourceTreeModel.removeEventListener(WebInspector.ResourceTreeModel.EventTypes.ViewportChanged, this._viewportChanged, this);
99     },
100
101     _invalidateCache: function()
102     {
103         delete this._cachedScale;
104         delete this._cachedCssCanvasWidth;
105         delete this._cachedCssCanvasHeight;
106         delete this._cachedCssHeight;
107         delete this._cachedCssWidth;
108         delete this._cachedZoomFactor;
109         delete this._cachedViewport;
110         delete this._cachedDrawContentsSize;
111         delete this._availableSize;
112     },
113
114     _emulationEnabledChanged: function()
115     {
116         var enabled = WebInspector.overridesSupport.emulationEnabled();
117         this._mediaInspector.setEnabled(enabled);
118         if (enabled && !this._enabled) {
119             this._invalidateCache();
120             this._ignoreResize = true;
121             this._enabled = true;
122             this._inspectedPagePlaceholder.clearMinimumSizeAndMargins();
123             this._inspectedPagePlaceholder.show(this._pageContainer);
124             this._responsiveDesignContainer.show(this.element);
125             delete this._ignoreResize;
126             this.onResize();
127         } else if (!enabled && this._enabled) {
128             this._invalidateCache();
129             this._ignoreResize = true;
130             this._enabled = false;
131             this._scale = 1;
132             this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins();
133             this._responsiveDesignContainer.detach();
134             this._inspectedPagePlaceholder.show(this.element);
135             delete this._ignoreResize;
136             this.onResize();
137         }
138     },
139
140     /**
141      * WebInspector.OverridesSupport.PageResizer override.
142      * @param {number} dipWidth
143      * @param {number} dipHeight
144      * @param {number} scale
145      */
146     update: function(dipWidth, dipHeight, scale)
147     {
148         this._scale = scale;
149         this._dipWidth = dipWidth ? Math.max(dipWidth, 1) : 0;
150         this._dipHeight = dipHeight ? Math.max(dipHeight, 1) : 0;
151         this._updateUI();
152     },
153
154     updatePageResizer: function()
155     {
156         WebInspector.overridesSupport.setPageResizer(this, this._availableDipSize());
157     },
158
159     /**
160      * @return {!Size}
161      */
162     _availableDipSize: function()
163     {
164         if (typeof this._availableSize === "undefined") {
165             var zoomFactor = WebInspector.zoomManager.zoomFactor();
166             var rect = this._canvasContainer.element.getBoundingClientRect();
167             this._availableSize = new Size(Math.max(rect.width * zoomFactor - WebInspector.ResponsiveDesignView.RulerWidth, 1),
168                                            Math.max(rect.height * zoomFactor - WebInspector.ResponsiveDesignView.RulerWidth, 1));
169         }
170         return this._availableSize;
171     },
172
173     /**
174      * @param {!Element} element
175      * @param {boolean} vertical
176      * @return {!WebInspector.ResizerWidget}
177      */
178     _createResizer: function(element, vertical)
179     {
180         var resizer = new WebInspector.ResizerWidget();
181         resizer.addElement(element);
182         resizer.setVertical(vertical);
183         resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeStart, this._onResizeStart, this);
184         resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate, this._onResizeUpdate, this);
185         resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeEnd, this._onResizeEnd, this);
186         return resizer;
187     },
188
189     /**
190      * @param {!WebInspector.Event} event
191      */
192     _onResizeStart: function(event)
193     {
194         this._drawContentsSize = false;
195         var available = this._availableDipSize();
196         this._slowPositionStart = null;
197         this._resizeStartSize = event.target.isVertical() ? (this._dipHeight || available.height) : (this._dipWidth || available.width);
198         this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.Events.FixedScaleRequested, true);
199         this._updateUI();
200     },
201
202     /**
203      * @param {!WebInspector.Event} event
204      */
205     _onResizeUpdate: function(event)
206     {
207         if (event.data.shiftKey !== !!this._slowPositionStart)
208             this._slowPositionStart = event.data.shiftKey ? event.data.currentPosition : null;
209         var cssOffset = this._slowPositionStart ? (event.data.currentPosition - this._slowPositionStart) / 10 + this._slowPositionStart - event.data.startPosition : event.data.currentPosition - event.data.startPosition;
210         var dipOffset = Math.round(cssOffset * WebInspector.zoomManager.zoomFactor());
211         var newSize = this._resizeStartSize + dipOffset;
212         newSize = Math.round(newSize / (this._scale || 1));
213         newSize = Math.max(Math.min(newSize, WebInspector.OverridesSupport.MaxDeviceSize), 1);
214         var requested = {};
215         if (event.target.isVertical())
216             requested.height = newSize;
217         else
218             requested.width = newSize;
219         this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.Events.ResizeRequested, requested);
220     },
221
222     /**
223      * @param {!WebInspector.Event} event
224      */
225     _onResizeEnd: function(event)
226     {
227         this._drawContentsSize = true;
228         this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.Events.FixedScaleRequested, false);
229         delete this._resizeStartSize;
230         this._updateUI();
231     },
232
233     /**
234      * Draws canvas of the specified css size in DevTools page space.
235      * Canvas contains grid and rulers.
236      * @param {number} cssCanvasWidth
237      * @param {number} cssCanvasHeight
238      */
239     _drawCanvas: function(cssCanvasWidth, cssCanvasHeight)
240     {
241         if (!this._enabled)
242             return;
243
244         var canvas = this._canvas;
245         var context = canvas.getContext("2d");
246         canvas.style.width = cssCanvasWidth + "px";
247         canvas.style.height = cssCanvasHeight + "px";
248
249         var zoomFactor = WebInspector.zoomManager.zoomFactor();
250         var dipCanvasWidth = cssCanvasWidth * zoomFactor;
251         var dipCanvasHeight = cssCanvasHeight * zoomFactor;
252
253         var deviceScaleFactor = window.devicePixelRatio;
254         canvas.width = deviceScaleFactor * cssCanvasWidth;
255         canvas.height = deviceScaleFactor * cssCanvasHeight;
256         context.scale(canvas.width / dipCanvasWidth, canvas.height / dipCanvasHeight);
257         context.font = "11px " + WebInspector.fontFamily();
258
259         const rulerBackgroundColor = "rgb(0, 0, 0)";
260         const backgroundColor = "rgb(102, 102, 102)";
261         const lightLineColor = "rgb(132, 132, 132)";
262         const darkLineColor = "rgb(114, 114, 114)";
263         const rulerColor = "rgb(125, 125, 125)";
264         const textColor = "rgb(186, 186, 186)";
265         const contentsSizeColor = "rgba(0, 0, 0, 0.3)";
266
267         var scale = (this._scale || 1) * this._viewport.pageScaleFactor;
268         var rulerScale = 0.5;
269         while (Math.abs(rulerScale * scale - 1) > Math.abs((rulerScale + 0.5) * scale - 1))
270             rulerScale += 0.5;
271
272         var gridStep = 50 * scale * rulerScale;
273         var gridSubStep = 10 * scale * rulerScale;
274
275         var rulerSubStep = 5 * scale * rulerScale;
276         var rulerStepCount = 20;
277
278         var rulerWidth = WebInspector.ResponsiveDesignView.RulerWidth;
279         var dipGridWidth = dipCanvasWidth - rulerWidth;
280         var dipGridHeight = dipCanvasHeight - rulerWidth;
281         var dipScrollX = this._viewport.scrollX * scale;
282         var dipScrollY = this._viewport.scrollY * scale;
283         context.translate(rulerWidth, rulerWidth);
284
285         context.fillStyle = rulerBackgroundColor;
286         context.fillRect(-rulerWidth, -rulerWidth, dipGridWidth + rulerWidth, rulerWidth);
287         context.fillRect(-rulerWidth, 0, rulerWidth, dipGridHeight);
288
289         context.fillStyle = backgroundColor;
290         context.fillRect(0, 0, dipGridWidth, dipGridHeight);
291
292         context.translate(0.5, 0.5);
293         context.strokeStyle = rulerColor;
294         context.fillStyle = textColor;
295         context.lineWidth = 1;
296
297         // Draw vertical ruler.
298         context.save();
299         var minXIndex = Math.ceil(dipScrollX / rulerSubStep);
300         var maxXIndex = Math.floor((dipScrollX + dipGridWidth) / rulerSubStep);
301         context.translate(-dipScrollX, 0);
302         for (var index = minXIndex; index <= maxXIndex; index++) {
303             var x = index * rulerSubStep;
304             var y = -rulerWidth / 4;
305             if (!(index % (rulerStepCount / 4)))
306                 y = -rulerWidth / 2;
307             if (!(index % (rulerStepCount / 2)))
308                 y = -rulerWidth + 2;
309
310             if (!(index % rulerStepCount)) {
311                 context.save();
312                 context.translate(x, 0);
313                 context.fillText(Math.round(x / scale), 2, -rulerWidth / 2);
314                 context.restore();
315                 y = -rulerWidth;
316             }
317
318             context.beginPath();
319             context.moveTo(x, y);
320             context.lineTo(x, 0);
321             context.stroke();
322         }
323         context.restore();
324
325         // Draw horizontal ruler.
326         context.save();
327         var minYIndex = Math.ceil(dipScrollY / rulerSubStep);
328         var maxYIndex = Math.floor((dipScrollY + dipGridHeight) / rulerSubStep);
329         context.translate(0, -dipScrollY);
330         for (var index = minYIndex; index <= maxYIndex; index++) {
331             var y = index * rulerSubStep;
332             var x = -rulerWidth / 4;
333             if (!(index % (rulerStepCount / 4)))
334                 x = -rulerWidth / 2;
335             if (!(index % (rulerStepCount / 2)))
336                 x = -rulerWidth + 2;
337
338             if (!(index % rulerStepCount)) {
339                 context.save();
340                 context.translate(0, y);
341                 context.rotate(-Math.PI / 2);
342                 context.fillText(Math.round(y / scale), 2, -rulerWidth / 2);
343                 context.restore();
344                 x = -rulerWidth;
345             }
346
347             context.beginPath();
348             context.moveTo(x, y);
349             context.lineTo(0, y);
350             context.stroke();
351         }
352         context.restore();
353
354         // Draw grid.
355         drawGrid(dipScrollX, dipScrollY, darkLineColor, gridSubStep);
356         drawGrid(dipScrollX, dipScrollY, lightLineColor, gridStep);
357
358         /**
359          * @param {number} scrollX
360          * @param {number} scrollY
361          * @param {string} color
362          * @param {number} step
363          */
364         function drawGrid(scrollX, scrollY, color, step)
365         {
366             context.strokeStyle = color;
367             var minX = Math.ceil(scrollX / step) * step;
368             var maxX = Math.floor((scrollX + dipGridWidth) / step) * step - minX;
369             var minY = Math.ceil(scrollY / step) * step;
370             var maxY = Math.floor((scrollY + dipGridHeight) / step) * step - minY;
371
372             context.save();
373             context.translate(minX - scrollX, 0);
374             for (var x = 0; x <= maxX; x += step) {
375                 context.beginPath();
376                 context.moveTo(x, 0);
377                 context.lineTo(x, dipGridHeight);
378                 context.stroke();
379             }
380             context.restore();
381
382             context.save();
383             context.translate(0, minY - scrollY);
384             for (var y = 0; y <= maxY; y += step) {
385                 context.beginPath();
386                 context.moveTo(0, y);
387                 context.lineTo(dipGridWidth, y);
388                 context.stroke();
389             }
390             context.restore();
391         }
392
393         context.translate(-0.5, -0.5);
394
395         // Draw contents size.
396         var pageScaleAvailable = WebInspector.overridesSupport.settings.emulateMobile.get() || WebInspector.overridesSupport.settings.emulateTouch.get();
397         if (this._drawContentsSize && pageScaleAvailable) {
398             context.fillStyle = contentsSizeColor;
399             var visibleContentsWidth = Math.max(0, Math.min(dipGridWidth, this._viewport.contentsWidth * scale - dipScrollX));
400             var visibleContentsHeight = Math.max(0, Math.min(dipGridHeight, this._viewport.contentsHeight * scale - dipScrollY));
401             context.fillRect(0, 0, visibleContentsWidth, visibleContentsHeight);
402         }
403     },
404
405     _updateUI: function()
406     {
407         if (!this._enabled || !this.isShowing())
408             return;
409
410         var zoomFactor = WebInspector.zoomManager.zoomFactor();
411         var rect = this._canvas.parentElement.getBoundingClientRect();
412         var availableDip = this._availableDipSize();
413         var cssCanvasWidth = rect.width;
414         var cssCanvasHeight = rect.height;
415
416         this._mediaInspector.setAxisTransform(WebInspector.ResponsiveDesignView.RulerWidth / zoomFactor, this._viewport.scrollX, this._scale * this._viewport.pageScaleFactor);
417
418         if (this._cachedZoomFactor !== zoomFactor) {
419             var cssRulerWidth = WebInspector.ResponsiveDesignView.RulerWidth / zoomFactor + "px";
420             this._rulerGlasspane.style.height = cssRulerWidth;
421             this._rulerGlasspane.style.left = cssRulerWidth;
422             this._slidersContainer.style.left = cssRulerWidth;
423             this._slidersContainer.style.top = cssRulerWidth;
424             this._warningMessage.style.height = cssRulerWidth;
425
426             var cssSliderWidth = WebInspector.ResponsiveDesignView.SliderWidth / zoomFactor + "px";
427             this._heightSliderContainer.style.flexBasis = cssSliderWidth;
428             this._heightSliderContainer.style.marginBottom = "-" + cssSliderWidth;
429             this._widthSliderContainer.style.flexBasis = cssSliderWidth;
430             this._widthSliderContainer.style.marginRight = "-" + cssSliderWidth;
431         }
432
433         var cssWidth = this._dipWidth ? (this._dipWidth / zoomFactor + "px") : (availableDip.width / zoomFactor + "px");
434         var cssHeight = this._dipHeight ? (this._dipHeight / zoomFactor + "px") : (availableDip.height / zoomFactor + "px");
435         if (this._cachedCssWidth !== cssWidth || this._cachedCssHeight !== cssHeight) {
436             this._slidersContainer.style.width = cssWidth;
437             this._slidersContainer.style.height = cssHeight;
438             this._inspectedPagePlaceholder.onResize();
439         }
440
441         var viewportChanged = !this._cachedViewport
442             || this._cachedViewport.scrollX !== this._viewport.scrollX || this._cachedViewport.scrollY !== this._viewport.scrollY
443             || this._cachedViewport.contentsWidth !== this._viewport.contentsWidth || this._cachedViewport.contentsHeight !== this._viewport.contentsHeight
444             || this._cachedViewport.pageScaleFactor !== this._viewport.pageScaleFactor;
445         if (viewportChanged || this._drawContentsSize !== this._cachedDrawContentsSize || this._cachedScale !== this._scale || this._cachedCssCanvasWidth !== cssCanvasWidth || this._cachedCssCanvasHeight !== cssCanvasHeight || this._cachedZoomFactor !== zoomFactor)
446             this._drawCanvas(cssCanvasWidth, cssCanvasHeight);
447
448         this._cachedScale = this._scale;
449         this._cachedCssCanvasWidth = cssCanvasWidth;
450         this._cachedCssCanvasHeight = cssCanvasHeight;
451         this._cachedCssHeight = cssHeight;
452         this._cachedCssWidth = cssWidth;
453         this._cachedZoomFactor = zoomFactor;
454         this._cachedViewport = this._viewport;
455         this._cachedDrawContentsSize = this._drawContentsSize;
456     },
457
458     onResize: function()
459     {
460         if (!this._enabled || this._ignoreResize)
461             return;
462         var oldSize = this._availableSize;
463         delete this._availableSize;
464         var newSize = this._availableDipSize();
465         if (!newSize.isEqual(oldSize))
466             this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.Events.AvailableSizeChanged, newSize);
467         this._updateUI();
468         this._inspectedPagePlaceholder.onResize();
469     },
470
471     _onZoomChanged: function()
472     {
473         this._updateUI();
474     },
475
476     _createToolbar: function()
477     {
478         this._toolbarElement = this._responsiveDesignContainer.element.createChild("div", "responsive-design-toolbar");
479         this._createButtonsSection();
480         this._toolbarElement.createChild("div", "responsive-design-separator");
481         this._createDeviceSection();
482         this._toolbarElement.createChild("div", "responsive-design-separator");
483         this._createNetworkSection();
484         this._toolbarElement.createChild("div", "responsive-design-separator");
485
486         var moreButtonContainer = this._toolbarElement.createChild("div", "responsive-design-more-button-container");
487         var moreButton = moreButtonContainer.createChild("button", "responsive-design-more-button");
488         moreButton.title = WebInspector.UIString("More overrides");
489         moreButton.addEventListener("click", this._showEmulationInDrawer.bind(this), false);
490         moreButton.textContent = "\u2026";
491     },
492
493     _createButtonsSection: function()
494     {
495         var buttonsSection = this._toolbarElement.createChild("div", "responsive-design-section responsive-design-section-buttons");
496
497         var resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Reset all overrides."), "clear-status-bar-item");
498         buttonsSection.appendChild(resetButton.element);
499         resetButton.addEventListener("click", WebInspector.overridesSupport.reset, WebInspector.overridesSupport);
500
501         // Media Query Inspector.
502         this._toggleMediaInspectorButton = new WebInspector.StatusBarButton(WebInspector.UIString("Media queries."), "responsive-design-toggle-media-inspector");
503         this._toggleMediaInspectorButton.toggled = WebInspector.settings.showMediaQueryInspector.get();
504         this._toggleMediaInspectorButton.addEventListener("click", this._onToggleMediaInspectorButtonClick, this);
505         WebInspector.settings.showMediaQueryInspector.addChangeListener(this._updateMediaQueryInspector, this);
506         buttonsSection.appendChild(this._toggleMediaInspectorButton.element);
507     },
508
509     _createDeviceSection: function()
510     {
511         var deviceSection = this._toolbarElement.createChild("div", "responsive-design-section responsive-design-section-device");
512
513         // Device.
514         var deviceElement = deviceSection.createChild("div", "responsive-design-suite responsive-design-suite-top").createChild("div");
515         var fieldsetElement = deviceElement.createChild("fieldset");
516         fieldsetElement.createChild("label").textContent = WebInspector.UIString("Device");
517         var deviceSelectElement = WebInspector.OverridesUI.createDeviceSelect(document);
518         fieldsetElement.appendChild(deviceSelectElement);
519         deviceSelectElement.classList.add("responsive-design-device-select");
520
521         var separator = deviceSection.createChild("div", "responsive-design-section-separator");
522
523         var detailsElement = deviceSection.createChild("div", "responsive-design-suite");
524
525         // Dimensions.
526         var screenElement = detailsElement.createChild("div", "");
527         fieldsetElement = screenElement.createChild("fieldset");
528
529         var emulateResolutionCheckbox = WebInspector.SettingsUI.createSettingCheckbox("", WebInspector.overridesSupport.settings.emulateResolution, true, undefined, WebInspector.UIString("Emulate screen resolution"));
530         fieldsetElement.appendChild(emulateResolutionCheckbox);
531
532         var resolutionButton = new WebInspector.StatusBarButton(WebInspector.UIString("Screen resolution"), "responsive-design-icon responsive-design-icon-resolution");
533         resolutionButton.setEnabled(false);
534         fieldsetElement.appendChild(resolutionButton.element);
535         var resolutionFieldset = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.emulateResolution);
536         fieldsetElement.appendChild(resolutionFieldset);
537
538         resolutionFieldset.appendChild(WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceWidth, true, 4, "3em", WebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UIString("\u2013")));
539         resolutionFieldset.appendChild(document.createTextNode(" \u00D7 "));
540         resolutionFieldset.appendChild(WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceHeight, true, 4, "3em", WebInspector.OverridesSupport.deviceSizeValidator, true, true, WebInspector.UIString("\u2013")));
541
542         var swapButton = new WebInspector.StatusBarButton(WebInspector.UIString("Swap dimensions"), "responsive-design-icon responsive-design-icon-swap");
543         swapButton.element.tabIndex = -1;
544         swapButton.addEventListener("click", WebInspector.overridesSupport.swapDimensions, WebInspector.overridesSupport);
545         resolutionFieldset.appendChild(swapButton.element);
546
547         // Device pixel ratio.
548         detailsElement.createChild("div", "responsive-design-suite-separator");
549
550         var dprElement = detailsElement.createChild("div", "");
551         var resolutionFieldset2 = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.emulateResolution);
552         dprElement.appendChild(resolutionFieldset2);
553         var dprButton = new WebInspector.StatusBarButton(WebInspector.UIString("Device pixel ratio"), "responsive-design-icon responsive-design-icon-dpr");
554         dprButton.setEnabled(false);
555         resolutionFieldset2.appendChild(dprButton.element);
556         resolutionFieldset2.appendChild(WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceScaleFactor, true, 4, "2.5em", WebInspector.OverridesSupport.deviceScaleFactorValidator, true, true, WebInspector.UIString("\u2013")));
557
558         // Fit to window.
559         detailsElement.createChild("div", "responsive-design-suite-separator");
560         var fitToWindowElement = detailsElement.createChild("div", "");
561         fieldsetElement = fitToWindowElement.createChild("fieldset");
562         fieldsetElement.appendChild(WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Fit"), WebInspector.overridesSupport.settings.deviceFitWindow, true, undefined, WebInspector.UIString("Zoom to fit available space")));
563     },
564
565     _createNetworkSection: function()
566     {
567         var networkSection = this._toolbarElement.createChild("div", "responsive-design-section responsive-design-section-network");
568
569         // Bandwidth.
570         var bandwidthElement = networkSection.createChild("div", "responsive-design-suite responsive-design-suite-top").createChild("div");
571         var fieldsetElement = bandwidthElement.createChild("fieldset");
572         var networkCheckbox = fieldsetElement.createChild("label");
573         networkCheckbox.textContent = WebInspector.UIString("Network");
574         fieldsetElement.appendChild(WebInspector.OverridesUI.createNetworkConditionsSelect(document));
575
576         var separator = networkSection.createChild("div", "responsive-design-section-separator");
577
578         // User agent.
579         var userAgentElement = networkSection.createChild("div", "responsive-design-suite").createChild("div");
580         fieldsetElement = userAgentElement.createChild("fieldset");
581         fieldsetElement.appendChild(WebInspector.SettingsUI.createSettingInputField("UA", WebInspector.overridesSupport.settings.userAgent, false, 0, "", undefined, false, false, WebInspector.UIString("No override")));
582     },
583
584     _onToggleMediaInspectorButtonClick: function()
585     {
586         WebInspector.settings.showMediaQueryInspector.set(!this._toggleMediaInspectorButton.toggled);
587     },
588
589     _updateMediaQueryInspector: function()
590     {
591         this._toggleMediaInspectorButton.toggled = WebInspector.settings.showMediaQueryInspector.get();
592         if (this._mediaInspector.isShowing() === WebInspector.settings.showMediaQueryInspector.get())
593             return;
594         if (this._mediaInspector.isShowing())
595             this._mediaInspector.detach();
596         else
597             this._mediaInspector.show(this._mediaInspectorContainer);
598         this.onResize();
599     },
600
601     _overridesWarningUpdated: function()
602     {
603         var message = WebInspector.overridesSupport.warningMessage();
604         if (this._warningMessage.querySelector("span").textContent === message)
605             return;
606         this._warningMessage.classList.toggle("hidden", !message);
607         this._warningMessage.querySelector("span").textContent = message;
608         this._invalidateCache();
609         this.onResize();
610     },
611
612     _showEmulationInDrawer: function()
613     {
614         WebInspector.Revealer.reveal(WebInspector.overridesSupport);
615     },
616
617     /**
618      * @param {!WebInspector.Event} event
619      */
620     _viewportChanged: function(event)
621     {
622         var viewport = /** @type {?PageAgent.Viewport} */ (event.data);
623         if (viewport) {
624             this._viewport = viewport;
625             this._viewportChangedThrottler.schedule(this._updateUIThrottled.bind(this));
626         }
627     },
628
629     /**
630      * @param {!WebInspector.Throttler.FinishCallback} finishCallback
631      */
632     _updateUIThrottled: function(finishCallback)
633     {
634         this._updateUI();
635         finishCallback();
636     },
637
638     __proto__: WebInspector.VBox.prototype
639 };