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 * @param {!WebInspector.InspectedPagePlaceholder} inspectedPagePlaceholder | |
10 */ | |
11 WebInspector.ResponsiveDesignView = function(inspectedPagePlaceholder) | |
12 { | |
13 WebInspector.VBox.call(this); | |
14 this.registerRequiredCSS("responsiveDesignView.css"); | |
15 | |
16 this._container = new WebInspector.View(); | |
17 this._container.element.classList.add("responsive-design"); | |
18 | |
19 this._canvas = this._container.element.createChild("canvas", "fill"); | |
20 this._resetButton = this._container.element.createChild("div", "responsive-d
esign-reset-button"); | |
21 this._resetButton.addEventListener("click", this._reset.bind(this), false); | |
22 this._resetButton.title = WebInspector.UIString("Fit available space"); | |
23 | |
24 this._slidersContainer = this._container.element.createChild("div", "vbox re
sponsive-design-sliders-container"); | |
25 var hbox = this._slidersContainer.createChild("div", "hbox flex-auto"); | |
26 this._heightSliderContainer = this._slidersContainer.createChild("div", "hbo
x responsive-design-slider-height"); | |
27 this._pageContainer = hbox.createChild("div", "vbox flex-auto"); | |
28 this._widthSliderContainer = hbox.createChild("div", "vbox responsive-design
-slider-width"); | |
29 | |
30 this._widthSlider = this._widthSliderContainer.createChild("div", "responsiv
e-design-slider-thumb"); | |
31 this._createResizer(this._widthSlider, false); | |
32 this._widthZeroButton = this._widthSlider.createChild("div", "responsive-des
ign-zero-button"); | |
33 this._widthZeroButton.addEventListener("click", this._zeroButtonClicked.bind
(this, false)); | |
34 this._heightSlider = this._heightSliderContainer.createChild("div", "respons
ive-design-slider-thumb"); | |
35 this._createResizer(this._heightSlider, true); | |
36 this._heightZeroButton = this._heightSlider.createChild("div", "responsive-d
esign-zero-button"); | |
37 this._heightZeroButton.addEventListener("click", this._zeroButtonClicked.bin
d(this, true)); | |
38 | |
39 this._inspectedPagePlaceholder = inspectedPagePlaceholder; | |
40 inspectedPagePlaceholder.show(this.element); | |
41 | |
42 this._enabled = false; | |
43 | |
44 WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.Zo
omChanged, this._onZoomChanged, this); | |
45 WebInspector.dockController.addEventListener(WebInspector.DockController.Eve
nts.DockSideChanged, this._updateOverridesSupportOnDockSideChange, this); | |
46 this._updateOverridesSupportOnDockSideChange(); | |
47 }; | |
48 | |
49 // Measured in DIP. | |
50 WebInspector.ResponsiveDesignView.SliderWidth = 19; | |
51 WebInspector.ResponsiveDesignView.RulerWidth = 23; | |
52 | |
53 WebInspector.ResponsiveDesignView.prototype = { | |
54 _updateOverridesSupportOnDockSideChange: function() | |
55 { | |
56 WebInspector.overridesSupport.setPageResizer(WebInspector.dockController
.dockSide() !== WebInspector.DockController.State.Undocked ? this : null); | |
57 }, | |
58 | |
59 /** | |
60 * WebInspector.OverridesSupport.PageResizer override. | |
61 * @param {number} dipWidth | |
62 * @param {number} dipHeight | |
63 * @param {number} scale | |
64 */ | |
65 enable: function(dipWidth, dipHeight, scale) | |
66 { | |
67 if (!this._enabled) { | |
68 this._ignoreResize = true; | |
69 this._enabled = true; | |
70 this._inspectedPagePlaceholder.clearMinimumSizeAndMargins(); | |
71 this._inspectedPagePlaceholder.show(this._pageContainer); | |
72 this._container.show(this.element); | |
73 delete this._ignoreResize; | |
74 } | |
75 | |
76 this._scale = scale; | |
77 this._dipWidth = dipWidth; | |
78 this._dipHeight = dipHeight; | |
79 this._updateUI(); | |
80 }, | |
81 | |
82 /** | |
83 * WebInspector.OverridesSupport.PageResizer override. | |
84 */ | |
85 disable: function() | |
86 { | |
87 if (!this._enabled) | |
88 return; | |
89 | |
90 this._ignoreResize = true; | |
91 this._enabled = false; | |
92 this._scale = 0; | |
93 this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins(); | |
94 this._container.detach(); | |
95 this._inspectedPagePlaceholder.show(this.element); | |
96 delete this._ignoreResize; | |
97 }, | |
98 | |
99 /** | |
100 * WebInspector.OverridesSupport.PageResizer override. | |
101 * @return {!Size} | |
102 */ | |
103 availableDipSize: function() | |
104 { | |
105 if (typeof this._availableSize === "undefined") { | |
106 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
107 var rect = this.element.getBoundingClientRect(); | |
108 this._availableSize = new Size(rect.width * zoomFactor - WebInspecto
r.ResponsiveDesignView.SliderWidth - WebInspector.ResponsiveDesignView.RulerWidt
h, | |
109 rect.height * zoomFactor - WebInspect
or.ResponsiveDesignView.SliderWidth - WebInspector.ResponsiveDesignView.RulerWid
th); | |
110 } | |
111 return this._availableSize; | |
112 }, | |
113 | |
114 /** | |
115 * @param {!Element} element | |
116 * @param {boolean} vertical | |
117 * @return {!WebInspector.ResizerWidget} | |
118 */ | |
119 _createResizer: function(element, vertical) | |
120 { | |
121 var resizer = new WebInspector.ResizerWidget(); | |
122 resizer.addElement(element); | |
123 resizer.setVertical(vertical); | |
124 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeStart,
this._onResizeStart, this); | |
125 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate,
this._onResizeUpdate, this); | |
126 resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeEnd, th
is._onResizeEnd, this); | |
127 return resizer; | |
128 }, | |
129 | |
130 /** | |
131 * @param {!WebInspector.Event} event | |
132 */ | |
133 _onResizeStart: function(event) | |
134 { | |
135 var available = this.availableDipSize(); | |
136 this._resizeStartSize = event.target.isVertical() ? (this._dipHeight ||
available.height) : (this._dipWidth || available.width); | |
137 }, | |
138 | |
139 /** | |
140 * @param {!WebInspector.Event} event | |
141 */ | |
142 _onResizeUpdate: function(event) | |
143 { | |
144 var cssOffset = event.data.currentPosition - event.data.startPosition; | |
145 var dipOffset = cssOffset * WebInspector.zoomManager.zoomFactor(); | |
146 var newSize = this._resizeStartSize + dipOffset; | |
147 var requested = new Size(this._dipWidth, this._dipHeight); | |
148 if (event.target.isVertical()) | |
149 requested.height = Number.constrain(newSize, 1, this.availableDipSiz
e().height); | |
150 else | |
151 requested.width = Number.constrain(newSize, 1, this.availableDipSize
().width); | |
152 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.ResizeRequested, requested); | |
153 }, | |
154 | |
155 /** | |
156 * @param {!WebInspector.Event} event | |
157 */ | |
158 _onResizeEnd: function(event) | |
159 { | |
160 delete this._resizeStartSize; | |
161 }, | |
162 | |
163 /** | |
164 * @param {boolean} isHeight | |
165 */ | |
166 _zeroButtonClicked: function(isHeight) | |
167 { | |
168 var size = new Size(this._dipWidth, this._dipHeight); | |
169 var available = this.availableDipSize(); | |
170 if (isHeight) | |
171 size.height = this._dipHeight ? 0 : available.height; | |
172 else | |
173 size.width = this._dipWidth ? 0 : available.width; | |
174 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.ResizeRequested, size); | |
175 }, | |
176 | |
177 /** | |
178 * Draws canvas of the specified css size in DevTools page space. | |
179 * Canvas contains grid and rulers. | |
180 * @param {number} cssCanvasWidth | |
181 * @param {number} cssCanvasHeight | |
182 */ | |
183 _drawCanvas: function(cssCanvasWidth, cssCanvasHeight) | |
184 { | |
185 if (!this._enabled) | |
186 return; | |
187 | |
188 var canvas = this._canvas; | |
189 var context = canvas.getContext("2d"); | |
190 canvas.style.width = cssCanvasWidth + "px"; | |
191 canvas.style.height = cssCanvasHeight + "px"; | |
192 | |
193 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
194 var dipCanvasWidth = cssCanvasWidth * zoomFactor; | |
195 var dipCanvasHeight = cssCanvasHeight * zoomFactor; | |
196 | |
197 var deviceScaleFactor = window.devicePixelRatio; | |
198 canvas.width = deviceScaleFactor * cssCanvasWidth; | |
199 canvas.height = deviceScaleFactor * cssCanvasHeight; | |
200 context.scale(canvas.width / dipCanvasWidth, canvas.height / dipCanvasHe
ight); | |
201 | |
202 context.font = "10px " + WebInspector.monospaceFontFamily(); | |
203 | |
204 const gridSubStep = 10; | |
205 const gridStep = 50; | |
206 const rulerBackgroundColor = "rgb(54, 54, 54)"; | |
207 const backgroundColor = "rgb(102, 102, 102)"; | |
208 const lightLineColor = "rgb(132, 132, 132)"; | |
209 const darkLineColor = "rgb(114, 114, 114)"; | |
210 const textColor = "rgb(180, 180, 180)"; | |
211 | |
212 var scale = this._scale || 1; | |
213 var rulerWidth = WebInspector.ResponsiveDesignView.RulerWidth; | |
214 var dipGridWidth = dipCanvasWidth / scale - rulerWidth; | |
215 var dipGridHeight = dipCanvasHeight / scale - rulerWidth; | |
216 rulerWidth /= scale; | |
217 context.scale(scale, scale); | |
218 context.translate(rulerWidth, rulerWidth); | |
219 | |
220 context.fillStyle = rulerBackgroundColor; | |
221 context.fillRect(0, -rulerWidth, dipGridWidth, rulerWidth); | |
222 context.fillRect(-rulerWidth, 0, rulerWidth, dipGridHeight); | |
223 | |
224 context.fillStyle = backgroundColor; | |
225 context.fillRect(0, 0, dipGridWidth, dipGridHeight); | |
226 | |
227 context.translate(0.5, 0.5); | |
228 context.fillStyle = textColor; | |
229 context.lineWidth = 1; | |
230 | |
231 { | |
232 // Draw vertical lines. | |
233 for (var x = 0; x < dipGridWidth; x += gridSubStep) { | |
234 var color = darkLineColor; | |
235 var y = -rulerWidth / 6; | |
236 if (!(x % (2 * gridSubStep))) | |
237 y = -rulerWidth / 3; | |
238 if (!(x % gridStep)) { | |
239 if (x) { | |
240 context.save(); | |
241 context.translate(x, 0); | |
242 context.fillText(x, 2, -rulerWidth / 2); | |
243 context.restore(); | |
244 } | |
245 y = -rulerWidth; | |
246 color = lightLineColor; | |
247 } | |
248 context.strokeStyle = color; | |
249 | |
250 context.beginPath(); | |
251 context.moveTo(x, y); | |
252 context.lineTo(x, dipGridHeight); | |
253 context.stroke(); | |
254 } | |
255 } | |
256 | |
257 { | |
258 // Draw horizontal lines. | |
259 for (var y = 0; y < dipGridHeight; y += gridSubStep) { | |
260 var color = darkLineColor; | |
261 var x = -rulerWidth / 6; | |
262 if (!(y % (2 * gridSubStep))) | |
263 x = -rulerWidth / 3; | |
264 if (!(y % gridStep)) { | |
265 if (y) { | |
266 context.save(); | |
267 context.translate(0, y); | |
268 context.rotate(-Math.PI / 2); | |
269 context.fillText(y, 2, -rulerWidth / 2); | |
270 context.restore(); | |
271 } | |
272 x = -rulerWidth; | |
273 color = lightLineColor; | |
274 } | |
275 context.strokeStyle = color; | |
276 | |
277 context.beginPath(); | |
278 context.moveTo(x, y); | |
279 context.lineTo(dipGridWidth, y); | |
280 context.stroke(); | |
281 } | |
282 context.restore(); | |
283 } | |
284 }, | |
285 | |
286 _updateUI: function() | |
287 { | |
288 if (!this._enabled) | |
289 return; | |
290 | |
291 var zoomFactor = WebInspector.zoomManager.zoomFactor(); | |
292 var rect = this._canvas.parentElement.getBoundingClientRect(); | |
293 var availableDip = this.availableDipSize(); | |
294 var cssCanvasWidth = rect.width; | |
295 var cssCanvasHeight = rect.height; | |
296 | |
297 this._widthSlider.classList.toggle("hidden", !!this._scale); | |
298 this._heightSlider.classList.toggle("hidden", !!this._scale); | |
299 this._widthSlider.classList.toggle("reversed", !this._dipWidth); | |
300 this._heightSlider.classList.toggle("reversed", !this._dipHeight); | |
301 | |
302 if (this._cachedZoomFactor !== zoomFactor) { | |
303 var cssRulerWidth = WebInspector.ResponsiveDesignView.RulerWidth / z
oomFactor + "px"; | |
304 this._resetButton.style.width = cssRulerWidth; | |
305 this._resetButton.style.height = cssRulerWidth; | |
306 this._slidersContainer.style.left = cssRulerWidth; | |
307 this._slidersContainer.style.top = cssRulerWidth; | |
308 | |
309 var cssSliderWidth = WebInspector.ResponsiveDesignView.SliderWidth /
zoomFactor + "px"; | |
310 this._heightSliderContainer.style.flexBasis = cssSliderWidth; | |
311 this._heightSliderContainer.style.marginBottom = "-" + cssSliderWidt
h; | |
312 this._widthSliderContainer.style.flexBasis = cssSliderWidth; | |
313 this._widthSliderContainer.style.marginRight = "-" + cssSliderWidth; | |
314 } | |
315 | |
316 var cssWidth = this._dipWidth ? (this._dipWidth / zoomFactor + "px") : (
availableDip.width / zoomFactor + "px"); | |
317 var cssHeight = this._dipHeight ? (this._dipHeight / zoomFactor + "px")
: (availableDip.height / zoomFactor + "px"); | |
318 if (this._cachedCssWidth !== cssWidth || this._cachedCssHeight !== cssHe
ight) { | |
319 this._slidersContainer.style.width = cssWidth; | |
320 this._slidersContainer.style.height = cssHeight; | |
321 this._inspectedPagePlaceholder.onResize(); | |
322 } | |
323 | |
324 if (this._cachedScale !== this._scale || this._cachedCssCanvasWidth !==
cssCanvasWidth || this._cachedCssCanvasHeight !== cssCanvasHeight || this._cache
dZoomFactor !== zoomFactor) | |
325 this._drawCanvas(cssCanvasWidth, cssCanvasHeight); | |
326 | |
327 this._cachedScale = this._scale; | |
328 this._cachedCssCanvasWidth = cssCanvasWidth; | |
329 this._cachedCssCanvasHeight = cssCanvasHeight; | |
330 this._cachedCssHeight = cssHeight; | |
331 this._cachedCssWidth = cssWidth; | |
332 this._cachedZoomFactor = zoomFactor; | |
333 }, | |
334 | |
335 onResize: function() | |
336 { | |
337 if (!this._enabled || this._ignoreResize) | |
338 return; | |
339 delete this._availableSize; | |
340 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.AvailableSizeChanged); | |
341 this._updateUI(); | |
342 }, | |
343 | |
344 _onZoomChanged: function() | |
345 { | |
346 this._updateUI(); | |
347 }, | |
348 | |
349 /** | |
350 * Resets emulated size to available space. | |
351 */ | |
352 _reset: function() | |
353 { | |
354 this.dispatchEventToListeners(WebInspector.OverridesSupport.PageResizer.
Events.ResizeRequested, this.availableDipSize()); | |
355 }, | |
356 | |
357 __proto__: WebInspector.VBox.prototype | |
358 }; | |
OLD | NEW |