| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |