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

Side by Side Diff: Source/devtools/front_end/Layers3DView.js

Issue 177353005: Layers view: Extract zoom/pan/rotate logic into transorm controller (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2014 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
(...skipping 22 matching lines...) Expand all
35 */ 35 */
36 WebInspector.Layers3DView = function(model) 36 WebInspector.Layers3DView = function(model)
37 { 37 {
38 WebInspector.View.call(this); 38 WebInspector.View.call(this);
39 this.element.classList.add("layers-3d-view"); 39 this.element.classList.add("layers-3d-view");
40 this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("Not in t he composited mode.\nConsider forcing composited mode in Settings.")); 40 this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("Not in t he composited mode.\nConsider forcing composited mode in Settings."));
41 this._model = model; 41 this._model = model;
42 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerTreeCha nged, this._update, this); 42 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerTreeCha nged, this._update, this);
43 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerPainted , this._onLayerPainted, this); 43 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerPainted , this._onLayerPainted, this);
44 this._rotatingContainerElement = this.element.createChild("div", "fill rotat ing-container"); 44 this._rotatingContainerElement = this.element.createChild("div", "fill rotat ing-container");
45 this.element.addEventListener("mousemove", this._onMouseMove.bind(this), fal se); 45 this._transformController = new WebInspector.TransformController(this.elemen t);
46 this.element.addEventListener("mouseout", this._onMouseMove.bind(this), fals e); 46 this._transformController.addEventListener(WebInspector.TransformController. Events.TransformChanged, this._onTransformChanged, this);
47 this.element.addEventListener("mousedown", this._onMouseDown.bind(this), fal se);
48 this.element.addEventListener("mouseup", this._onMouseUp.bind(this), false);
49 this.element.addEventListener("contextmenu", this._onContextMenu.bind(this), false);
50 this.element.addEventListener("dblclick", this._onDoubleClick.bind(this), fa lse); 47 this.element.addEventListener("dblclick", this._onDoubleClick.bind(this), fa lse);
51 this.element.addEventListener("click", this._onClick.bind(this), false); 48 this.element.addEventListener("click", this._onClick.bind(this), false);
49 this.element.addEventListener("mousemove", this._onMouseMove.bind(this), fal se);
50 this.element.addEventListener("contextmenu", this._onContextMenu.bind(this), false);
52 this._elementsByLayerId = {}; 51 this._elementsByLayerId = {};
53 this._rotateX = 0;
54 this._rotateY = 0;
55 this._scaleAdjustmentStylesheet = this.element.ownerDocument.head.createChil d("style"); 52 this._scaleAdjustmentStylesheet = this.element.ownerDocument.head.createChil d("style");
56 this._scaleAdjustmentStylesheet.disabled = true; 53 this._scaleAdjustmentStylesheet.disabled = true;
57 this._lastOutlinedElement = {}; 54 this._lastOutlinedElement = {};
58 this._layerImage = document.createElement("img"); 55 this._layerImage = document.createElement("img");
56 this._layerImage.style.width = "100%";
57 this._layerImage.style.height = "100%";
59 WebInspector.settings.showPaintRects.addChangeListener(this._update, this); 58 WebInspector.settings.showPaintRects.addChangeListener(this._update, this);
60 } 59 }
61 60
62 /** 61 /**
63 * @enum {string} 62 * @enum {string}
64 */ 63 */
65 WebInspector.Layers3DView.OutlineType = { 64 WebInspector.Layers3DView.OutlineType = {
66 Hovered: "hovered", 65 Hovered: "hovered",
67 Selected: "selected" 66 Selected: "selected"
68 } 67 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 if (imageURL) 148 if (imageURL)
150 this._layerImage.src = imageURL; 149 this._layerImage.src = imageURL;
151 element.appendChild(this._layerImage); 150 element.appendChild(this._layerImage);
152 }, 151 },
153 152
154 _scaleToFit: function() 153 _scaleToFit: function()
155 { 154 {
156 var root = this._model.contentRoot(); 155 var root = this._model.contentRoot();
157 if (!root) 156 if (!root)
158 return; 157 return;
158
159 const padding = 40; 159 const padding = 40;
160 var scaleX = this._clientWidth / (root.width() + 2 * padding); 160 var scaleX = this._clientWidth / (root.width() + 2 * padding);
161 var scaleY = this._clientHeight / (root.height() + 2 * padding); 161 var scaleY = this._clientHeight / (root.height() + 2 * padding);
162 this._scale = Math.min(scaleX, scaleY); 162 var autoScale = Math.min(scaleX, scaleY);
163 163
164 this._scale = autoScale * this._transformController.scale();
165 this._paddingX = ((this._clientWidth / autoScale - root.width()) >> 1) * this._scale;
166 this._paddingY = ((this._clientHeight / autoScale - root.height()) >> 1) * this._scale;
164 const screenLayerSpacing = 20; 167 const screenLayerSpacing = 20;
165 this._layerSpacing = Math.ceil(screenLayerSpacing / this._scale) + "px"; 168 this._layerSpacing = screenLayerSpacing + "px";
166 const screenLayerThickness = 4; 169 const screenLayerThickness = 4;
167 var layerThickness = Math.ceil(screenLayerThickness / this._scale) + "px "; 170 var layerThickness = screenLayerThickness + "px";
171
168 var stylesheetContent = ".layer-container .side-wall { height: " + layer Thickness + "; width: " + layerThickness + "; } " + 172 var stylesheetContent = ".layer-container .side-wall { height: " + layer Thickness + "; width: " + layerThickness + "; } " +
169 ".layer-container .back-wall { -webkit-transform: translateZ(-" + la yerThickness + "); } " + 173 ".layer-container .back-wall { -webkit-transform: translateZ(-" + la yerThickness + "); } " +
170 ".layer-container { -webkit-transform: translateZ(" + this._layerSpa cing + "); }"; 174 ".layer-container { -webkit-transform: translateZ(" + this._layerSpa cing + "); }";
171 // Workaround for double style recalculation upon assignment to style sh eet's text content. 175 // Workaround for double style recalculation upon assignment to style sh eet's text content.
172 var stylesheetTextNode = this._scaleAdjustmentStylesheet.firstChild; 176 var stylesheetTextNode = this._scaleAdjustmentStylesheet.firstChild;
173 if (!stylesheetTextNode || stylesheetTextNode.nodeType !== Node.TEXT_NOD E || stylesheetTextNode.nextSibling) 177 if (!stylesheetTextNode || stylesheetTextNode.nodeType !== Node.TEXT_NOD E || stylesheetTextNode.nextSibling)
174 this._scaleAdjustmentStylesheet.textContent = stylesheetContent; 178 this._scaleAdjustmentStylesheet.textContent = stylesheetContent;
175 else 179 else
176 stylesheetTextNode.nodeValue = stylesheetContent; 180 stylesheetTextNode.nodeValue = stylesheetContent;
177 var element = this._elementForLayer(root); 181
178 element.style.webkitTransform = "scale3d(" + this._scale + "," + this._s cale + "," + this._scale + ")"; 182 var style = this._elementForLayer(root).style;
179 element.style.webkitTransformOrigin = ""; 183 style.left = this._paddingX + "px";
180 element.style.left = ((this._clientWidth - root.width() * this._scale) > > 1) + "px"; 184 style.top = this._paddingY + "px";
181 element.style.top = ((this._clientHeight - root.height() * this._scale) >> 1) + "px"; 185 style.webkitTransformOrigin = "";
186 },
187
188 /**
189 * @param {!WebInspector.Event} event
190 */
191 _onTransformChanged: function(event)
192 {
193 var changedTransforms = /** @type {number} */ (event.data);
194 if (changedTransforms & WebInspector.TransformController.TransformType.S cale)
195 this._update();
196 else
197 this._updateTransform();
198 },
199
200 _updateTransform: function()
201 {
202 var root = this._model.contentRoot();
203 if (!root)
204 return;
205 var offsetX = this._transformController.offsetX();
206 var offsetY = this._transformController.offsetY();
207 var style = this._rotatingContainerElement.style;
208 // Translate well to front so that no matter how we turn the plane, no p arts of it goes below parent.
209 // This makes sure mouse events go to proper layers, not straight to the parent.
210 style.webkitTransform = "translateZ(10000px)" +
211 " rotateX(" + this._transformController.rotateX() + "deg) rotateY(" + this._transformController.rotateY() + "deg)" +
212 " translateX(" + offsetX + "px) translateY(" + offsetY + "px)";
213 // Compute where the center of shitfted and scaled root layer would be a nd use is as origin for rotation.
214 style.webkitTransformOrigin = Math.round(this._paddingX + offsetX + root .width() * this._scale / 2) + "px " + Math.round(this._paddingY + offsetY + root .height() * this._scale / 2) + "px";
182 }, 215 },
183 216
184 _update: function() 217 _update: function()
185 { 218 {
186 if (!this.isShowing()) { 219 if (!this.isShowing()) {
187 this._needsUpdate = true; 220 this._needsUpdate = true;
188 return; 221 return;
189 } 222 }
190 if (!this._model.contentRoot()) { 223 if (!this._model.contentRoot()) {
191 this._emptyView.show(this.element); 224 this._emptyView.show(this.element);
(...skipping 11 matching lines...) Expand all
203 } 236 }
204 this._clientWidth = this.element.clientWidth; 237 this._clientWidth = this.element.clientWidth;
205 this._clientHeight = this.element.clientHeight; 238 this._clientHeight = this.element.clientHeight;
206 for (var layerId in this._elementsByLayerId) { 239 for (var layerId in this._elementsByLayerId) {
207 if (this._model.layerById(layerId)) 240 if (this._model.layerById(layerId))
208 continue; 241 continue;
209 this._elementsByLayerId[layerId].remove(); 242 this._elementsByLayerId[layerId].remove();
210 delete this._elementsByLayerId[layerId]; 243 delete this._elementsByLayerId[layerId];
211 } 244 }
212 this._scaleToFit(); 245 this._scaleToFit();
246 this._updateTransform();
213 this._model.forEachLayer(updateLayer.bind(this), this._model.contentRoot ()); 247 this._model.forEachLayer(updateLayer.bind(this), this._model.contentRoot ());
214 this._needsUpdate = false; 248 this._needsUpdate = false;
215 }, 249 },
216 250
217 /** 251 /**
218 * @param {!WebInspector.Event} event 252 * @param {!WebInspector.Event} event
219 */ 253 */
220 _onLayerPainted: function(event) 254 _onLayerPainted: function(event)
221 { 255 {
222 var layer = /** @type {!WebInspector.Layer} */ (event.data); 256 var layer = /** @type {!WebInspector.Layer} */ (event.data);
(...skipping 29 matching lines...) Expand all
252 var layer = element.__layerDetails.layer; 286 var layer = element.__layerDetails.layer;
253 var style = element.style; 287 var style = element.style;
254 var isContentRoot = layer === this._model.contentRoot(); 288 var isContentRoot = layer === this._model.contentRoot();
255 var parentElement = isContentRoot ? this._rotatingContainerElement : thi s._elementForLayer(layer.parent()); 289 var parentElement = isContentRoot ? this._rotatingContainerElement : thi s._elementForLayer(layer.parent());
256 element.__layerDetails.depth = parentElement.__layerDetails ? parentElem ent.__layerDetails.depth + 1 : 0; 290 element.__layerDetails.depth = parentElement.__layerDetails ? parentElem ent.__layerDetails.depth + 1 : 0;
257 element.enableStyleClass("invisible", layer.invisible()); 291 element.enableStyleClass("invisible", layer.invisible());
258 this._updateElementColor(element); 292 this._updateElementColor(element);
259 if (parentElement !== element.parentElement) 293 if (parentElement !== element.parentElement)
260 parentElement.appendChild(element); 294 parentElement.appendChild(element);
261 295
262 style.width = layer.width() + "px"; 296 style.width = layer.width() * this._scale + "px";
263 style.height = layer.height() + "px"; 297 style.height = layer.height() * this._scale + "px";
264 this._updatePaintRect(element); 298 this._updatePaintRect(element);
265 if (isContentRoot) 299 if (isContentRoot)
266 return; 300 return;
267 301 style.left = layer.offsetX() * this._scale + "px";
268 style.left = layer.offsetX() + "px"; 302 style.top = layer.offsetY() * this._scale + "px";
269 style.top = layer.offsetY() + "px";
270 var transform = layer.transform(); 303 var transform = layer.transform();
271 if (transform) { 304 if (transform) {
305 transform = transform.slice();
306 // Adjust offset in the transform matrix according to scale.
307 for (var i = 12; i < 15; ++i)
308 transform[i] *= this._scale;
272 // Avoid exponential notation in CSS. 309 // Avoid exponential notation in CSS.
273 style.webkitTransform = "matrix3d(" + transform.map(toFixed5).join(" ,") + ") translateZ(" + this._layerSpacing + ")"; 310 style.webkitTransform = "matrix3d(" + transform.map(toFixed5).join(" ,") + ") translateZ(" + this._layerSpacing + ")";
274 var anchor = layer.anchorPoint(); 311 var anchor = layer.anchorPoint();
275 style.webkitTransformOrigin = Math.round(anchor[0] * 100) + "% " + M ath.round(anchor[1] * 100) + "% " + anchor[2]; 312 style.webkitTransformOrigin = Math.round(anchor[0] * 100) + "% " + M ath.round(anchor[1] * 100) + "% " + anchor[2];
276 } else { 313 } else {
277 style.webkitTransform = ""; 314 style.webkitTransform = "";
278 style.webkitTransformOrigin = ""; 315 style.webkitTransformOrigin = "";
279 } 316 }
280 317
281 function toFixed5(x) 318 function toFixed5(x)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 else { 355 else {
319 const base = 144; 356 const base = 144;
320 var component = base + 20 * ((element.__layerDetails.depth - 1) % 5) ; 357 var component = base + 20 * ((element.__layerDetails.depth - 1) % 5) ;
321 color = "rgba(" + component + "," + component + "," + component + ", 0.8)"; 358 color = "rgba(" + component + "," + component + "," + component + ", 0.8)";
322 } 359 }
323 element.style.backgroundColor = color; 360 element.style.backgroundColor = color;
324 }, 361 },
325 362
326 /** 363 /**
327 * @param {?Event} event 364 * @param {?Event} event
328 */
329 _onMouseDown: function(event)
330 {
331 if (event.which !== 1)
332 return;
333 this._setReferencePoint(event);
334 },
335
336 /**
337 * @param {?Event} event
338 */
339 _setReferencePoint: function(event)
340 {
341 this._originX = event.clientX;
342 this._originY = event.clientY;
343 this._oldRotateX = this._rotateX;
344 this._oldRotateY = this._rotateY;
345 },
346
347 _resetReferencePoint: function()
348 {
349 delete this._originX;
350 delete this._originY;
351 delete this._oldRotateX;
352 delete this._oldRotateY;
353 },
354
355 /**
356 * @param {?Event} event
357 */
358 _onMouseUp: function(event)
359 {
360 if (event.which !== 1)
361 return;
362 this._resetReferencePoint();
363 },
364
365 /**
366 * @param {?Event} event
367 * @return {?WebInspector.Layer} 365 * @return {?WebInspector.Layer}
368 */ 366 */
369 _layerFromEventPoint: function(event) 367 _layerFromEventPoint: function(event)
370 { 368 {
371 var element = this.element.ownerDocument.elementFromPoint(event.pageX, e vent.pageY); 369 var element = this.element.ownerDocument.elementFromPoint(event.pageX, e vent.pageY);
372 if (!element) 370 if (!element)
373 return null; 371 return null;
374 element = element.enclosingNodeOrSelfWithClass("layer-container"); 372 element = element.enclosingNodeOrSelfWithClass("layer-container");
375 return element && element.__layerDetails && element.__layerDetails.layer ; 373 return element && element.__layerDetails && element.__layerDetails.layer ;
376 }, 374 },
377 375
378 /** 376 /**
379 * @param {?Event} event 377 * @param {?Event} event
380 */ 378 */
381 _onMouseMove: function(event)
382 {
383 if (!event.which) {
384 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.Layer Hovered, this._layerFromEventPoint(event));
385 return;
386 }
387 if (event.which === 1) {
388 // Set reference point if we missed mousedown.
389 if (typeof this._originX !== "number")
390 this._setReferencePoint(event);
391 this._rotateX = this._oldRotateX + (this._originY - event.clientY) / 2;
392 this._rotateY = this._oldRotateY - (this._originX - event.clientX) / 4;
393 // Translate well to front so that no matter how we turn the plane, no parts of it goes below parent.
394 // This makes sure mouse events go to proper layers, not straight to the parent.
395 this._rotatingContainerElement.style.webkitTransform = "translateZ(1 0000px) rotateX(" + this._rotateX + "deg) rotateY(" + this._rotateY + "deg)";
396 }
397 },
398
399 /**
400 * @param {?Event} event
401 */
402 _onContextMenu: function(event) 379 _onContextMenu: function(event)
403 { 380 {
404 var layer = this._layerFromEventPoint(event); 381 var layer = this._layerFromEventPoint(event);
405 var nodeId = layer && layer.nodeId(); 382 var nodeId = layer && layer.nodeId();
406 if (!nodeId) 383 if (!nodeId)
407 return; 384 return;
408 var domNode = WebInspector.domAgent.nodeForId(nodeId); 385 var domNode = WebInspector.domAgent.nodeForId(nodeId);
409 if (!domNode) 386 if (!domNode)
410 return; 387 return;
411 var contextMenu = new WebInspector.ContextMenu(event); 388 var contextMenu = new WebInspector.ContextMenu(event);
412 contextMenu.appendApplicableItems(domNode); 389 contextMenu.appendApplicableItems(domNode);
413 contextMenu.show(); 390 contextMenu.show();
414 }, 391 },
415 392
416 /** 393 /**
417 * @param {?Event} event 394 * @param {?Event} event
418 */ 395 */
396 _onMouseMove: function(event)
397 {
398 if (event.which)
399 return;
400 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.LayerHove red, this._layerFromEventPoint(event));
401 },
402
403 /**
404 * @param {?Event} event
405 */
419 _onClick: function(event) 406 _onClick: function(event)
420 { 407 {
421 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.LayerSele cted, this._layerFromEventPoint(event)); 408 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.LayerSele cted, this._layerFromEventPoint(event));
422 }, 409 },
423 410
424 /** 411 /**
425 * @param {?Event} event 412 * @param {?Event} event
426 */ 413 */
427 _onDoubleClick: function(event) 414 _onDoubleClick: function(event)
428 { 415 {
(...skipping 11 matching lines...) Expand all
440 * @param {!WebInspector.Layer} layer 427 * @param {!WebInspector.Layer} layer
441 * @param {!Element} paintRectElement 428 * @param {!Element} paintRectElement
442 */ 429 */
443 WebInspector.LayerDetails = function(layer, paintRectElement) 430 WebInspector.LayerDetails = function(layer, paintRectElement)
444 { 431 {
445 this.layer = layer; 432 this.layer = layer;
446 this.depth = 0; 433 this.depth = 0;
447 this.paintRectElement = paintRectElement; 434 this.paintRectElement = paintRectElement;
448 this.paintCount = 0; 435 this.paintCount = 0;
449 } 436 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698