The Great Blink mv for source files, part 2.
Move and rename files.
NOAUTOREVERT=true
NOPRESUBMIT=true
NOTREECHECKS=true
Bug: 768828
[email protected]
NOTRY=true
Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28
Reviewed-on: https://chromium-review.googlesource.com/1001153
Reviewed-by: Blink Reformat <[email protected]>
Commit-Queue: Blink Reformat <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#549061}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
diff --git a/front_end/elements/MetricsSidebarPane.js b/front_end/elements/MetricsSidebarPane.js
new file mode 100644
index 0000000..01b0ee4
--- /dev/null
+++ b/front_end/elements/MetricsSidebarPane.js
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @unrestricted
+ */
+Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
+ constructor() {
+ super();
+ this.registerRequiredCSS('elements/metricsSidebarPane.css');
+
+ /** @type {?SDK.CSSStyleDeclaration} */
+ this._inlineStyle = null;
+ }
+
+ /**
+ * @override
+ * @protected
+ * @return {!Promise.<?>}
+ */
+ doUpdate() {
+ // "style" attribute might have changed. Update metrics unless they are being edited
+ // (if a CSS property is added, a StyleSheetChanged event is dispatched).
+ if (this._isEditingMetrics)
+ return Promise.resolve();
+
+ // FIXME: avoid updates of a collapsed pane.
+ const node = this.node();
+ const cssModel = this.cssModel();
+ if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {
+ this.contentElement.removeChildren();
+ return Promise.resolve();
+ }
+
+ /**
+ * @param {?Map.<string, string>} style
+ * @this {Elements.MetricsSidebarPane}
+ */
+ function callback(style) {
+ if (!style || this.node() !== node)
+ return;
+ this._updateMetrics(style);
+ }
+ /**
+ * @param {?SDK.CSSModel.InlineStyleResult} inlineStyleResult
+ * @this {Elements.MetricsSidebarPane}
+ */
+ function inlineStyleCallback(inlineStyleResult) {
+ if (inlineStyleResult && this.node() === node)
+ this._inlineStyle = inlineStyleResult.inlineStyle;
+ }
+
+ const promises = [
+ cssModel.computedStylePromise(node.id).then(callback.bind(this)),
+ cssModel.inlineStylesPromise(node.id).then(inlineStyleCallback.bind(this))
+ ];
+ return Promise.all(promises);
+ }
+
+ /**
+ * @override
+ */
+ onCSSModelChanged() {
+ this.update();
+ }
+
+ /**
+ * @param {!Map.<string, string>} style
+ * @param {string} propertyName
+ * @return {number}
+ */
+ _getPropertyValueAsPx(style, propertyName) {
+ return Number(style.get(propertyName).replace(/px$/, '') || 0);
+ }
+
+ /**
+ * @param {!Map.<string, string>} computedStyle
+ * @param {string} componentName
+ */
+ _getBox(computedStyle, componentName) {
+ const suffix = componentName === 'border' ? '-width' : '';
+ const left = this._getPropertyValueAsPx(computedStyle, componentName + '-left' + suffix);
+ const top = this._getPropertyValueAsPx(computedStyle, componentName + '-top' + suffix);
+ const right = this._getPropertyValueAsPx(computedStyle, componentName + '-right' + suffix);
+ const bottom = this._getPropertyValueAsPx(computedStyle, componentName + '-bottom' + suffix);
+ return {left: left, top: top, right: right, bottom: bottom};
+ }
+
+ /**
+ * @param {boolean} showHighlight
+ * @param {string} mode
+ * @param {!Event} event
+ */
+ _highlightDOMNode(showHighlight, mode, event) {
+ event.consume();
+ if (showHighlight && this.node()) {
+ if (this._highlightMode === mode)
+ return;
+ this._highlightMode = mode;
+ this.node().highlight(mode);
+ } else {
+ delete this._highlightMode;
+ SDK.OverlayModel.hideDOMNodeHighlight();
+ }
+
+ for (let i = 0; this._boxElements && i < this._boxElements.length; ++i) {
+ const element = this._boxElements[i];
+ if (!this.node() || mode === 'all' || element._name === mode)
+ element.style.backgroundColor = element._backgroundColor;
+ else
+ element.style.backgroundColor = '';
+ }
+ }
+
+ /**
+ * @param {!Map.<string, string>} style
+ */
+ _updateMetrics(style) {
+ // Updating with computed style.
+ const metricsElement = createElement('div');
+ metricsElement.className = 'metrics';
+ const self = this;
+
+ /**
+ * @param {!Map.<string, string>} style
+ * @param {string} name
+ * @param {string} side
+ * @param {string} suffix
+ * @this {Elements.MetricsSidebarPane}
+ */
+ function createBoxPartElement(style, name, side, suffix) {
+ const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;
+ let value = style.get(propertyName);
+ if (value === '' || (name !== 'position' && value === '0px'))
+ value = '\u2012';
+ else if (name === 'position' && value === 'auto')
+ value = '\u2012';
+ value = value.replace(/px$/, '');
+ value = Number.toFixedIfFloating(value);
+
+ const element = createElement('div');
+ element.className = side;
+ element.textContent = value;
+ element.addEventListener('dblclick', this.startEditing.bind(this, element, name, propertyName, style), false);
+ return element;
+ }
+
+ /**
+ * @param {!Map.<string, string>} style
+ * @return {string}
+ */
+ function getContentAreaWidthPx(style) {
+ let width = style.get('width').replace(/px$/, '');
+ if (!isNaN(width) && style.get('box-sizing') === 'border-box') {
+ const borderBox = self._getBox(style, 'border');
+ const paddingBox = self._getBox(style, 'padding');
+
+ width = width - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right;
+ }
+
+ return Number.toFixedIfFloating(width.toString());
+ }
+
+ /**
+ * @param {!Map.<string, string>} style
+ * @return {string}
+ */
+ function getContentAreaHeightPx(style) {
+ let height = style.get('height').replace(/px$/, '');
+ if (!isNaN(height) && style.get('box-sizing') === 'border-box') {
+ const borderBox = self._getBox(style, 'border');
+ const paddingBox = self._getBox(style, 'padding');
+
+ height = height - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom;
+ }
+
+ return Number.toFixedIfFloating(height.toString());
+ }
+
+ // Display types for which margin is ignored.
+ const noMarginDisplayType = {
+ 'table-cell': true,
+ 'table-column': true,
+ 'table-column-group': true,
+ 'table-footer-group': true,
+ 'table-header-group': true,
+ 'table-row': true,
+ 'table-row-group': true
+ };
+
+ // Display types for which padding is ignored.
+ const noPaddingDisplayType = {
+ 'table-column': true,
+ 'table-column-group': true,
+ 'table-footer-group': true,
+ 'table-header-group': true,
+ 'table-row': true,
+ 'table-row-group': true
+ };
+
+ // Position types for which top, left, bottom and right are ignored.
+ const noPositionType = {'static': true};
+
+ const boxes = ['content', 'padding', 'border', 'margin', 'position'];
+ const boxColors = [
+ Common.Color.PageHighlight.Content, Common.Color.PageHighlight.Padding, Common.Color.PageHighlight.Border,
+ Common.Color.PageHighlight.Margin, Common.Color.fromRGBA([0, 0, 0, 0])
+ ];
+ const boxLabels = [
+ Common.UIString('content'), Common.UIString('padding'), Common.UIString('border'), Common.UIString('margin'),
+ Common.UIString('position')
+ ];
+ let previousBox = null;
+ this._boxElements = [];
+ for (let i = 0; i < boxes.length; ++i) {
+ const name = boxes[i];
+
+ if (name === 'margin' && noMarginDisplayType[style.get('display')])
+ continue;
+ if (name === 'padding' && noPaddingDisplayType[style.get('display')])
+ continue;
+ if (name === 'position' && noPositionType[style.get('position')])
+ continue;
+
+ const boxElement = createElement('div');
+ boxElement.className = name;
+ boxElement._backgroundColor = boxColors[i].asString(Common.Color.Format.RGBA);
+ boxElement._name = name;
+ boxElement.style.backgroundColor = boxElement._backgroundColor;
+ boxElement.addEventListener(
+ 'mouseover', this._highlightDOMNode.bind(this, true, name === 'position' ? 'all' : name), false);
+ this._boxElements.push(boxElement);
+
+ if (name === 'content') {
+ const widthElement = createElement('span');
+ widthElement.textContent = getContentAreaWidthPx(style);
+ widthElement.addEventListener(
+ 'dblclick', this.startEditing.bind(this, widthElement, 'width', 'width', style), false);
+
+ const heightElement = createElement('span');
+ heightElement.textContent = getContentAreaHeightPx(style);
+ heightElement.addEventListener(
+ 'dblclick', this.startEditing.bind(this, heightElement, 'height', 'height', style), false);
+
+ boxElement.appendChild(widthElement);
+ boxElement.createTextChild(' \u00D7 ');
+ boxElement.appendChild(heightElement);
+ } else {
+ const suffix = (name === 'border' ? '-width' : '');
+
+ const labelElement = createElement('div');
+ labelElement.className = 'label';
+ labelElement.textContent = boxLabels[i];
+ boxElement.appendChild(labelElement);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, 'top', suffix));
+ boxElement.appendChild(createElement('br'));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, 'left', suffix));
+
+ if (previousBox)
+ boxElement.appendChild(previousBox);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, 'right', suffix));
+ boxElement.appendChild(createElement('br'));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, 'bottom', suffix));
+ }
+
+ previousBox = boxElement;
+ }
+
+ metricsElement.appendChild(previousBox);
+ metricsElement.addEventListener('mouseover', this._highlightDOMNode.bind(this, false, 'all'), false);
+ this.contentElement.removeChildren();
+ this.contentElement.appendChild(metricsElement);
+ }
+
+ /**
+ * @param {!Element} targetElement
+ * @param {string} box
+ * @param {string} styleProperty
+ * @param {!Map.<string, string>} computedStyle
+ */
+ startEditing(targetElement, box, styleProperty, computedStyle) {
+ if (UI.isBeingEdited(targetElement))
+ return;
+
+ const context = {box: box, styleProperty: styleProperty, computedStyle: computedStyle};
+ const boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty);
+ context.keyDownHandler = boundKeyDown;
+ targetElement.addEventListener('keydown', boundKeyDown, false);
+
+ this._isEditingMetrics = true;
+
+ const config =
+ new UI.InplaceEditor.Config(this._editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ UI.InplaceEditor.startEditing(targetElement, config);
+
+ targetElement.getComponentSelection().selectAllChildren(targetElement);
+ }
+
+ _handleKeyDown(context, styleProperty, event) {
+ const element = event.currentTarget;
+
+ /**
+ * @param {string} originalValue
+ * @param {string} replacementString
+ * @this {Elements.MetricsSidebarPane}
+ */
+ function finishHandler(originalValue, replacementString) {
+ this._applyUserInput(element, replacementString, originalValue, context, false);
+ }
+
+ /**
+ * @param {string} prefix
+ * @param {number} number
+ * @param {string} suffix
+ * @return {string}
+ */
+ function customNumberHandler(prefix, number, suffix) {
+ if (styleProperty !== 'margin' && number < 0)
+ number = 0;
+ return prefix + number + suffix;
+ }
+
+ UI.handleElementValueModifications(event, element, finishHandler.bind(this), undefined, customNumberHandler);
+ }
+
+ editingEnded(element, context) {
+ delete this.originalPropertyData;
+ delete this.previousPropertyDataCandidate;
+ element.removeEventListener('keydown', context.keyDownHandler, false);
+ delete this._isEditingMetrics;
+ }
+
+ editingCancelled(element, context) {
+ if ('originalPropertyData' in this && this._inlineStyle) {
+ if (!this.originalPropertyData) {
+ // An added property, remove the last property in the style.
+ const pastLastSourcePropertyIndex = this._inlineStyle.pastLastSourcePropertyIndex();
+ if (pastLastSourcePropertyIndex)
+ this._inlineStyle.allProperties()[pastLastSourcePropertyIndex - 1].setText('', false);
+ } else {
+ this._inlineStyle.allProperties()[this.originalPropertyData.index].setText(
+ this.originalPropertyData.propertyText, false);
+ }
+ }
+ this.editingEnded(element, context);
+ this.update();
+ }
+
+ _applyUserInput(element, userInput, previousContent, context, commitEditor) {
+ if (!this._inlineStyle) {
+ // Element has no renderer.
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+ }
+
+ if (commitEditor && userInput === previousContent)
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+
+ if (context.box !== 'position' && (!userInput || userInput === '\u2012'))
+ userInput = '0px';
+ else if (context.box === 'position' && (!userInput || userInput === '\u2012'))
+ userInput = 'auto';
+
+ userInput = userInput.toLowerCase();
+ // Append a "px" unit if the user input was just a number.
+ if (/^\d+$/.test(userInput))
+ userInput += 'px';
+
+ const styleProperty = context.styleProperty;
+ const computedStyle = context.computedStyle;
+
+ if (computedStyle.get('box-sizing') === 'border-box' && (styleProperty === 'width' || styleProperty === 'height')) {
+ if (!userInput.match(/px$/)) {
+ Common.console.error(
+ 'For elements with box-sizing: border-box, only absolute content area dimensions can be applied');
+ return;
+ }
+
+ const borderBox = this._getBox(computedStyle, 'border');
+ const paddingBox = this._getBox(computedStyle, 'padding');
+ let userValuePx = Number(userInput.replace(/px$/, ''));
+ if (isNaN(userValuePx))
+ return;
+ if (styleProperty === 'width')
+ userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right;
+ else
+ userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;
+
+ userInput = userValuePx + 'px';
+ }
+
+ this.previousPropertyDataCandidate = null;
+
+ const allProperties = this._inlineStyle.allProperties();
+ for (let i = 0; i < allProperties.length; ++i) {
+ const property = allProperties[i];
+ if (property.name !== context.styleProperty || !property.activeInStyle())
+ continue;
+
+ this.previousPropertyDataCandidate = property;
+ property.setValue(userInput, commitEditor, true, callback.bind(this));
+ return;
+ }
+
+ this._inlineStyle.appendProperty(context.styleProperty, userInput, callback.bind(this));
+
+ /**
+ * @param {boolean} success
+ * @this {Elements.MetricsSidebarPane}
+ */
+ function callback(success) {
+ if (!success)
+ return;
+ if (!('originalPropertyData' in this))
+ this.originalPropertyData = this.previousPropertyDataCandidate;
+
+ if (typeof this._highlightMode !== 'undefined')
+ this.node().highlight(this._highlightMode);
+
+ if (commitEditor)
+ this.update();
+ }
+ }
+
+ _editingCommitted(element, userInput, previousContent, context) {
+ this.editingEnded(element, context);
+ this._applyUserInput(element, userInput, previousContent, context, true);
+ }
+};