Index: third_party/WebKit/Source/devtools/front_end/ui/Widget.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Widget.js b/third_party/WebKit/Source/devtools/front_end/ui/Widget.js |
index c14e5b86aed93382997eb800be1d7ccda6e00d12..07b09d919269effa2a627cc4bf7ac01ebedd9937 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/ui/Widget.js |
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Widget.js |
@@ -23,21 +23,22 @@ |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
- |
/** |
- * @constructor |
- * @extends {WebInspector.Object} |
- * @param {boolean=} isWebComponent |
+ * @unrestricted |
*/ |
-WebInspector.Widget = function(isWebComponent) |
-{ |
- this.contentElement = createElementWithClass("div", "widget"); |
+WebInspector.Widget = class extends WebInspector.Object { |
+ /** |
+ * @param {boolean=} isWebComponent |
+ */ |
+ constructor(isWebComponent) { |
+ super(); |
+ this.contentElement = createElementWithClass('div', 'widget'); |
if (isWebComponent) { |
- this.element = createElementWithClass("div", "vbox flex-auto"); |
- this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.element); |
- this._shadowRoot.appendChild(this.contentElement); |
+ this.element = createElementWithClass('div', 'vbox flex-auto'); |
+ this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.element); |
+ this._shadowRoot.appendChild(this.contentElement); |
} else { |
- this.element = this.contentElement; |
+ this.element = this.contentElement; |
} |
this._isWebComponent = isWebComponent; |
this.element.__widget = this; |
@@ -49,550 +50,547 @@ WebInspector.Widget = function(isWebComponent) |
this._notificationDepth = 0; |
this._invalidationsSuspended = 0; |
this._defaultFocusedChild = null; |
-}; |
- |
-WebInspector.Widget.prototype = { |
- markAsRoot: function() |
- { |
- WebInspector.Widget.__assert(!this.element.parentElement, "Attempt to mark as root attached node"); |
- this._isRoot = true; |
- }, |
- |
- /** |
- * @return {?WebInspector.Widget} |
- */ |
- parentWidget: function() |
- { |
- return this._parentWidget; |
- }, |
- |
- /** |
- * @return {!Array.<!WebInspector.Widget>} |
- */ |
- children: function() |
- { |
- return this._children; |
- }, |
- |
- /** |
- * @param {!WebInspector.Widget} widget |
- * @protected |
- */ |
- childWasDetached: function(widget) |
- { |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- isShowing: function() |
- { |
- return this._isShowing; |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- shouldHideOnDetach: function() |
- { |
- if (!this.element.parentElement) |
- return false; |
- if (this._hideOnDetach) |
- return true; |
- for (var child of this._children) { |
- if (child.shouldHideOnDetach()) |
- return true; |
- } |
- return false; |
- }, |
- |
- setHideOnDetach: function() |
- { |
- this._hideOnDetach = true; |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- _inNotification: function() |
- { |
- return !!this._notificationDepth || (this._parentWidget && this._parentWidget._inNotification()); |
- }, |
- |
- _parentIsShowing: function() |
- { |
- if (this._isRoot) |
- return true; |
- return !!this._parentWidget && this._parentWidget.isShowing(); |
- }, |
- |
- /** |
- * @param {function(this:WebInspector.Widget)} method |
- */ |
- _callOnVisibleChildren: function(method) |
- { |
- var copy = this._children.slice(); |
- for (var i = 0; i < copy.length; ++i) { |
- if (copy[i]._parentWidget === this && copy[i]._visible) |
- method.call(copy[i]); |
- } |
- }, |
- |
- _processWillShow: function() |
- { |
- this._callOnVisibleChildren(this._processWillShow); |
- this._isShowing = true; |
- }, |
- |
- _processWasShown: function() |
- { |
- if (this._inNotification()) |
- return; |
- this.restoreScrollPositions(); |
- this._notify(this.wasShown); |
- this._callOnVisibleChildren(this._processWasShown); |
- }, |
- |
- _processWasDetachedFromHierarchy: function() |
- { |
- this._notify(this.wasDetachedFromHierarchy); |
- var copy = this._children.slice(); |
- for (var widget of copy) |
- widget._processWasDetachedFromHierarchy(); |
- }, |
- |
- _processWillHide: function() |
- { |
- if (this._inNotification()) |
- return; |
- this.storeScrollPositions(); |
- |
- this._callOnVisibleChildren(this._processWillHide); |
- this._notify(this.willHide); |
- this._isShowing = false; |
- }, |
- |
- _processWasHidden: function() |
- { |
- this._callOnVisibleChildren(this._processWasHidden); |
- }, |
- |
- _processOnResize: function() |
- { |
- if (this._inNotification()) |
- return; |
- if (!this.isShowing()) |
- return; |
- this._notify(this.onResize); |
- this._callOnVisibleChildren(this._processOnResize); |
- }, |
- |
- /** |
- * @param {function(this:WebInspector.Widget)} notification |
- */ |
- _notify: function(notification) |
- { |
- ++this._notificationDepth; |
- try { |
- notification.call(this); |
- } finally { |
- --this._notificationDepth; |
- } |
- }, |
- |
- wasShown: function() |
- { |
- }, |
- |
- willHide: function() |
- { |
- }, |
- |
- wasDetachedFromHierarchy: function() |
- { |
- }, |
- |
- onResize: function() |
- { |
- }, |
- |
- onLayout: function() |
- { |
- }, |
- |
- /** |
- * @param {!Element} parentElement |
- * @param {?Element=} insertBefore |
- */ |
- show: function(parentElement, insertBefore) |
- { |
- WebInspector.Widget.__assert(parentElement, "Attempt to attach widget with no parent element"); |
- |
- if (!this._isRoot) { |
- // Update widget hierarchy. |
- var currentParent = parentElement; |
- while (currentParent && !currentParent.__widget) |
- currentParent = currentParent.parentElementOrShadowHost(); |
- WebInspector.Widget.__assert(currentParent, "Attempt to attach widget to orphan node"); |
- this.attach(currentParent.__widget); |
- } |
+ } |
- this.showWidget(parentElement, insertBefore); |
- }, |
- |
- /** |
- * @param {!WebInspector.Widget} parentWidget |
- */ |
- attach: function(parentWidget) |
- { |
- if (parentWidget === this._parentWidget) |
- return; |
- if (this._parentWidget) |
- this.detach(); |
- this._parentWidget = parentWidget; |
- this._parentWidget._children.push(this); |
- this._isRoot = false; |
- }, |
- |
- /** |
- * @param {!Element} parentElement |
- * @param {?Element=} insertBefore |
- */ |
- showWidget: function(parentElement, insertBefore) |
- { |
- var currentParent = parentElement; |
- while (currentParent && !currentParent.__widget) |
- currentParent = currentParent.parentElementOrShadowHost(); |
- |
- if (this._isRoot) |
- WebInspector.Widget.__assert(!currentParent, "Attempt to show root widget under another widget"); |
- else |
- WebInspector.Widget.__assert(currentParent && currentParent.__widget === this._parentWidget, "Attempt to show under node belonging to alien widget"); |
- |
- var wasVisible = this._visible; |
- if (wasVisible && this.element.parentElement === parentElement) |
- return; |
- |
- this._visible = true; |
- |
- if (!wasVisible && this._parentIsShowing()) |
- this._processWillShow(); |
- |
- this.element.classList.remove("hidden"); |
- |
- // Reparent |
- if (this.element.parentElement !== parentElement) { |
- WebInspector.Widget._incrementWidgetCounter(parentElement, this.element); |
- if (insertBefore) |
- WebInspector.Widget._originalInsertBefore.call(parentElement, this.element, insertBefore); |
- else |
- WebInspector.Widget._originalAppendChild.call(parentElement, this.element); |
- } |
- |
- if (!wasVisible && this._parentIsShowing()) |
- this._processWasShown(); |
- |
- if (this._parentWidget && this._hasNonZeroConstraints()) |
- this._parentWidget.invalidateConstraints(); |
- else |
- this._processOnResize(); |
- }, |
- |
- hideWidget: function() |
- { |
- if (!this._parentWidget) |
- return; |
- this._hideWidget(); |
- }, |
- |
- /** |
- * @param {boolean=} overrideHideOnDetach |
- */ |
- _hideWidget: function(overrideHideOnDetach) |
- { |
- if (!this._visible) |
- return; |
- this._visible = false; |
- var parentElement = this.element.parentElement; |
- |
- if (this._parentIsShowing()) |
- this._processWillHide(); |
- |
- if (!overrideHideOnDetach && this.shouldHideOnDetach()) { |
- this.element.classList.add("hidden"); |
- } else { |
- // Force legal removal |
- WebInspector.Widget._decrementWidgetCounter(parentElement, this.element); |
- WebInspector.Widget._originalRemoveChild.call(parentElement, this.element); |
- } |
+ static _incrementWidgetCounter(parentElement, childElement) { |
+ var count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0); |
+ if (!count) |
+ return; |
- if (this._parentIsShowing()) |
- this._processWasHidden(); |
- if (this._parentWidget && this._hasNonZeroConstraints()) |
- this._parentWidget.invalidateConstraints(); |
- }, |
- |
- detach: function() |
- { |
- if (!this._parentWidget && !this._isRoot) |
- return; |
- |
- if (this._visible) |
- this._hideWidget(true); |
- |
- // Update widget hierarchy. |
- if (this._parentWidget) { |
- var childIndex = this._parentWidget._children.indexOf(this); |
- WebInspector.Widget.__assert(childIndex >= 0, "Attempt to remove non-child widget"); |
- this._parentWidget._children.splice(childIndex, 1); |
- if (this._parentWidget._defaultFocusedChild === this) |
- this._parentWidget._defaultFocusedChild = null; |
- this._parentWidget.childWasDetached(this); |
- var parent = this._parentWidget; |
- this._parentWidget = null; |
- this._processWasDetachedFromHierarchy(); |
- } else { |
- WebInspector.Widget.__assert(this._isRoot, "Removing non-root widget from DOM"); |
- } |
- }, |
+ while (parentElement) { |
+ parentElement.__widgetCounter = (parentElement.__widgetCounter || 0) + count; |
+ parentElement = parentElement.parentElementOrShadowHost(); |
+ } |
+ } |
- detachChildWidgets: function() |
- { |
- var children = this._children.slice(); |
- for (var i = 0; i < children.length; ++i) |
- children[i].detach(); |
- }, |
+ static _decrementWidgetCounter(parentElement, childElement) { |
+ var count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0); |
+ if (!count) |
+ return; |
- /** |
- * @return {!Array.<!Element>} |
- */ |
- elementsToRestoreScrollPositionsFor: function() |
- { |
- return [this.element]; |
- }, |
- |
- storeScrollPositions: function() |
- { |
- var elements = this.elementsToRestoreScrollPositionsFor(); |
- for (var i = 0; i < elements.length; ++i) { |
- var container = elements[i]; |
- container._scrollTop = container.scrollTop; |
- container._scrollLeft = container.scrollLeft; |
- } |
- }, |
- |
- restoreScrollPositions: function() |
- { |
- var elements = this.elementsToRestoreScrollPositionsFor(); |
- for (var i = 0; i < elements.length; ++i) { |
- var container = elements[i]; |
- if (container._scrollTop) |
- container.scrollTop = container._scrollTop; |
- if (container._scrollLeft) |
- container.scrollLeft = container._scrollLeft; |
- } |
- }, |
- |
- doResize: function() |
- { |
- if (!this.isShowing()) |
- return; |
- // No matter what notification we are in, dispatching onResize is not needed. |
- if (!this._inNotification()) |
- this._callOnVisibleChildren(this._processOnResize); |
- }, |
- |
- doLayout: function() |
- { |
- if (!this.isShowing()) |
- return; |
- this._notify(this.onLayout); |
- this.doResize(); |
- }, |
+ while (parentElement) { |
+ parentElement.__widgetCounter -= count; |
+ parentElement = parentElement.parentElementOrShadowHost(); |
+ } |
+ } |
- /** |
- * @param {string} cssFile |
- */ |
- registerRequiredCSS: function(cssFile) |
- { |
- WebInspector.appendStyle(this._isWebComponent ? this._shadowRoot : this.element, cssFile); |
- }, |
+ static __assert(condition, message) { |
+ if (!condition) { |
+ console.trace(); |
+ throw new Error(message); |
+ } |
+ } |
- printWidgetHierarchy: function() |
- { |
- var lines = []; |
- this._collectWidgetHierarchy("", lines); |
- console.log(lines.join("\n")); |
- }, |
+ /** |
+ * @param {?Node} node |
+ */ |
+ static focusWidgetForNode(node) { |
+ while (node) { |
+ if (node.__widget) |
+ break; |
+ node = node.parentNodeOrShadowHost(); |
+ } |
+ if (!node) |
+ return; |
- _collectWidgetHierarchy: function(prefix, lines) |
- { |
- lines.push(prefix + "[" + this.element.className + "]" + (this._children.length ? " {" : "")); |
+ var widget = node.__widget; |
+ while (widget._parentWidget) { |
+ widget._parentWidget._defaultFocusedChild = widget; |
+ widget = widget._parentWidget; |
+ } |
+ } |
+ |
+ markAsRoot() { |
+ WebInspector.Widget.__assert(!this.element.parentElement, 'Attempt to mark as root attached node'); |
+ this._isRoot = true; |
+ } |
+ |
+ /** |
+ * @return {?WebInspector.Widget} |
+ */ |
+ parentWidget() { |
+ return this._parentWidget; |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.Widget>} |
+ */ |
+ children() { |
+ return this._children; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Widget} widget |
+ * @protected |
+ */ |
+ childWasDetached(widget) { |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ isShowing() { |
+ return this._isShowing; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ shouldHideOnDetach() { |
+ if (!this.element.parentElement) |
+ return false; |
+ if (this._hideOnDetach) |
+ return true; |
+ for (var child of this._children) { |
+ if (child.shouldHideOnDetach()) |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ setHideOnDetach() { |
+ this._hideOnDetach = true; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ _inNotification() { |
+ return !!this._notificationDepth || (this._parentWidget && this._parentWidget._inNotification()); |
+ } |
+ |
+ _parentIsShowing() { |
+ if (this._isRoot) |
+ return true; |
+ return !!this._parentWidget && this._parentWidget.isShowing(); |
+ } |
+ |
+ /** |
+ * @param {function(this:WebInspector.Widget)} method |
+ */ |
+ _callOnVisibleChildren(method) { |
+ var copy = this._children.slice(); |
+ for (var i = 0; i < copy.length; ++i) { |
+ if (copy[i]._parentWidget === this && copy[i]._visible) |
+ method.call(copy[i]); |
+ } |
+ } |
+ |
+ _processWillShow() { |
+ this._callOnVisibleChildren(this._processWillShow); |
+ this._isShowing = true; |
+ } |
+ |
+ _processWasShown() { |
+ if (this._inNotification()) |
+ return; |
+ this.restoreScrollPositions(); |
+ this._notify(this.wasShown); |
+ this._callOnVisibleChildren(this._processWasShown); |
+ } |
+ |
+ _processWasDetachedFromHierarchy() { |
+ this._notify(this.wasDetachedFromHierarchy); |
+ var copy = this._children.slice(); |
+ for (var widget of copy) |
+ widget._processWasDetachedFromHierarchy(); |
+ } |
+ |
+ _processWillHide() { |
+ if (this._inNotification()) |
+ return; |
+ this.storeScrollPositions(); |
+ |
+ this._callOnVisibleChildren(this._processWillHide); |
+ this._notify(this.willHide); |
+ this._isShowing = false; |
+ } |
+ |
+ _processWasHidden() { |
+ this._callOnVisibleChildren(this._processWasHidden); |
+ } |
+ |
+ _processOnResize() { |
+ if (this._inNotification()) |
+ return; |
+ if (!this.isShowing()) |
+ return; |
+ this._notify(this.onResize); |
+ this._callOnVisibleChildren(this._processOnResize); |
+ } |
+ |
+ /** |
+ * @param {function(this:WebInspector.Widget)} notification |
+ */ |
+ _notify(notification) { |
+ ++this._notificationDepth; |
+ try { |
+ notification.call(this); |
+ } finally { |
+ --this._notificationDepth; |
+ } |
+ } |
- for (var i = 0; i < this._children.length; ++i) |
- this._children[i]._collectWidgetHierarchy(prefix + " ", lines); |
+ wasShown() { |
+ } |
- if (this._children.length) |
- lines.push(prefix + "}"); |
- }, |
+ willHide() { |
+ } |
- /** |
- * @param {?Element} element |
- */ |
- setDefaultFocusedElement: function(element) |
- { |
- this._defaultFocusedElement = element; |
- }, |
+ wasDetachedFromHierarchy() { |
+ } |
- /** |
- * @param {!WebInspector.Widget} child |
- */ |
- setDefaultFocusedChild: function(child) |
- { |
- WebInspector.Widget.__assert(child._parentWidget === this, "Attempt to set non-child widget as default focused."); |
- this._defaultFocusedChild = child; |
- }, |
- |
- focus: function() |
- { |
- if (!this.isShowing()) |
- return; |
- |
- var element = this._defaultFocusedElement; |
- if (element) { |
- if (!element.hasFocus()) |
- element.focus(); |
- return; |
- } |
+ onResize() { |
+ } |
- if (this._defaultFocusedChild && this._defaultFocusedChild._visible) { |
- this._defaultFocusedChild.focus(); |
- } else { |
- for (var child of this._children) { |
- if (child._visible) { |
- child.focus(); |
- break; |
- } |
- } |
- } |
+ onLayout() { |
+ } |
- }, |
+ /** |
+ * @param {!Element} parentElement |
+ * @param {?Element=} insertBefore |
+ */ |
+ show(parentElement, insertBefore) { |
+ WebInspector.Widget.__assert(parentElement, 'Attempt to attach widget with no parent element'); |
- /** |
- * @return {boolean} |
- */ |
- hasFocus: function() |
- { |
- return this.element.hasFocus(); |
- }, |
+ if (!this._isRoot) { |
+ // Update widget hierarchy. |
+ var currentParent = parentElement; |
+ while (currentParent && !currentParent.__widget) |
+ currentParent = currentParent.parentElementOrShadowHost(); |
+ WebInspector.Widget.__assert(currentParent, 'Attempt to attach widget to orphan node'); |
+ this.attach(currentParent.__widget); |
+ } |
- /** |
- * @return {!Size} |
- */ |
- measurePreferredSize: function() |
- { |
- var document = this.element.ownerDocument; |
- var oldParent = this.element.parentElement; |
- var oldNextSibling = this.element.nextSibling; |
- |
- WebInspector.Widget._originalAppendChild.call(document.body, this.element); |
- this.element.positionAt(0, 0); |
- var result = new Size(this.element.offsetWidth, this.element.offsetHeight); |
- |
- this.element.positionAt(undefined, undefined); |
- if (oldParent) |
- WebInspector.Widget._originalInsertBefore.call(oldParent, this.element, oldNextSibling); |
- else |
- WebInspector.Widget._originalRemoveChild.call(document.body, this.element); |
- return result; |
- }, |
+ this.showWidget(parentElement, insertBefore); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Widget} parentWidget |
+ */ |
+ attach(parentWidget) { |
+ if (parentWidget === this._parentWidget) |
+ return; |
+ if (this._parentWidget) |
+ this.detach(); |
+ this._parentWidget = parentWidget; |
+ this._parentWidget._children.push(this); |
+ this._isRoot = false; |
+ } |
+ |
+ /** |
+ * @param {!Element} parentElement |
+ * @param {?Element=} insertBefore |
+ */ |
+ showWidget(parentElement, insertBefore) { |
+ var currentParent = parentElement; |
+ while (currentParent && !currentParent.__widget) |
+ currentParent = currentParent.parentElementOrShadowHost(); |
+ |
+ if (this._isRoot) |
+ WebInspector.Widget.__assert(!currentParent, 'Attempt to show root widget under another widget'); |
+ else |
+ WebInspector.Widget.__assert( |
+ currentParent && currentParent.__widget === this._parentWidget, |
+ 'Attempt to show under node belonging to alien widget'); |
+ |
+ var wasVisible = this._visible; |
+ if (wasVisible && this.element.parentElement === parentElement) |
+ return; |
+ |
+ this._visible = true; |
+ |
+ if (!wasVisible && this._parentIsShowing()) |
+ this._processWillShow(); |
+ |
+ this.element.classList.remove('hidden'); |
+ |
+ // Reparent |
+ if (this.element.parentElement !== parentElement) { |
+ WebInspector.Widget._incrementWidgetCounter(parentElement, this.element); |
+ if (insertBefore) |
+ WebInspector.Widget._originalInsertBefore.call(parentElement, this.element, insertBefore); |
+ else |
+ WebInspector.Widget._originalAppendChild.call(parentElement, this.element); |
+ } |
- /** |
- * @return {!Constraints} |
- */ |
- calculateConstraints: function() |
- { |
- return new Constraints(); |
- }, |
+ if (!wasVisible && this._parentIsShowing()) |
+ this._processWasShown(); |
+ |
+ if (this._parentWidget && this._hasNonZeroConstraints()) |
+ this._parentWidget.invalidateConstraints(); |
+ else |
+ this._processOnResize(); |
+ } |
+ |
+ hideWidget() { |
+ if (!this._parentWidget) |
+ return; |
+ this._hideWidget(); |
+ } |
+ |
+ /** |
+ * @param {boolean=} overrideHideOnDetach |
+ */ |
+ _hideWidget(overrideHideOnDetach) { |
+ if (!this._visible) |
+ return; |
+ this._visible = false; |
+ var parentElement = this.element.parentElement; |
- /** |
- * @return {!Constraints} |
- */ |
- constraints: function() |
- { |
- if (typeof this._constraints !== "undefined") |
- return this._constraints; |
- if (typeof this._cachedConstraints === "undefined") |
- this._cachedConstraints = this.calculateConstraints(); |
- return this._cachedConstraints; |
- }, |
+ if (this._parentIsShowing()) |
+ this._processWillHide(); |
- /** |
- * @param {number} width |
- * @param {number} height |
- * @param {number} preferredWidth |
- * @param {number} preferredHeight |
- */ |
- setMinimumAndPreferredSizes: function(width, height, preferredWidth, preferredHeight) |
- { |
- this._constraints = new Constraints(new Size(width, height), new Size(preferredWidth, preferredHeight)); |
- this.invalidateConstraints(); |
- }, |
+ if (!overrideHideOnDetach && this.shouldHideOnDetach()) { |
+ this.element.classList.add('hidden'); |
+ } else { |
+ // Force legal removal |
+ WebInspector.Widget._decrementWidgetCounter(parentElement, this.element); |
+ WebInspector.Widget._originalRemoveChild.call(parentElement, this.element); |
+ } |
- /** |
- * @param {number} width |
- * @param {number} height |
- */ |
- setMinimumSize: function(width, height) |
- { |
- this._constraints = new Constraints(new Size(width, height)); |
- this.invalidateConstraints(); |
- }, |
+ if (this._parentIsShowing()) |
+ this._processWasHidden(); |
+ if (this._parentWidget && this._hasNonZeroConstraints()) |
+ this._parentWidget.invalidateConstraints(); |
+ } |
+ |
+ detach() { |
+ if (!this._parentWidget && !this._isRoot) |
+ return; |
+ |
+ if (this._visible) |
+ this._hideWidget(true); |
+ |
+ // Update widget hierarchy. |
+ if (this._parentWidget) { |
+ var childIndex = this._parentWidget._children.indexOf(this); |
+ WebInspector.Widget.__assert(childIndex >= 0, 'Attempt to remove non-child widget'); |
+ this._parentWidget._children.splice(childIndex, 1); |
+ if (this._parentWidget._defaultFocusedChild === this) |
+ this._parentWidget._defaultFocusedChild = null; |
+ this._parentWidget.childWasDetached(this); |
+ var parent = this._parentWidget; |
+ this._parentWidget = null; |
+ this._processWasDetachedFromHierarchy(); |
+ } else { |
+ WebInspector.Widget.__assert(this._isRoot, 'Removing non-root widget from DOM'); |
+ } |
+ } |
+ |
+ detachChildWidgets() { |
+ var children = this._children.slice(); |
+ for (var i = 0; i < children.length; ++i) |
+ children[i].detach(); |
+ } |
+ |
+ /** |
+ * @return {!Array.<!Element>} |
+ */ |
+ elementsToRestoreScrollPositionsFor() { |
+ return [this.element]; |
+ } |
+ |
+ storeScrollPositions() { |
+ var elements = this.elementsToRestoreScrollPositionsFor(); |
+ for (var i = 0; i < elements.length; ++i) { |
+ var container = elements[i]; |
+ container._scrollTop = container.scrollTop; |
+ container._scrollLeft = container.scrollLeft; |
+ } |
+ } |
+ |
+ restoreScrollPositions() { |
+ var elements = this.elementsToRestoreScrollPositionsFor(); |
+ for (var i = 0; i < elements.length; ++i) { |
+ var container = elements[i]; |
+ if (container._scrollTop) |
+ container.scrollTop = container._scrollTop; |
+ if (container._scrollLeft) |
+ container.scrollLeft = container._scrollLeft; |
+ } |
+ } |
+ |
+ doResize() { |
+ if (!this.isShowing()) |
+ return; |
+ // No matter what notification we are in, dispatching onResize is not needed. |
+ if (!this._inNotification()) |
+ this._callOnVisibleChildren(this._processOnResize); |
+ } |
+ |
+ doLayout() { |
+ if (!this.isShowing()) |
+ return; |
+ this._notify(this.onLayout); |
+ this.doResize(); |
+ } |
+ |
+ /** |
+ * @param {string} cssFile |
+ */ |
+ registerRequiredCSS(cssFile) { |
+ WebInspector.appendStyle(this._isWebComponent ? this._shadowRoot : this.element, cssFile); |
+ } |
+ |
+ printWidgetHierarchy() { |
+ var lines = []; |
+ this._collectWidgetHierarchy('', lines); |
+ console.log(lines.join('\n')); |
+ } |
+ |
+ _collectWidgetHierarchy(prefix, lines) { |
+ lines.push(prefix + '[' + this.element.className + ']' + (this._children.length ? ' {' : '')); |
+ |
+ for (var i = 0; i < this._children.length; ++i) |
+ this._children[i]._collectWidgetHierarchy(prefix + ' ', lines); |
+ |
+ if (this._children.length) |
+ lines.push(prefix + '}'); |
+ } |
+ |
+ /** |
+ * @param {?Element} element |
+ */ |
+ setDefaultFocusedElement(element) { |
+ this._defaultFocusedElement = element; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Widget} child |
+ */ |
+ setDefaultFocusedChild(child) { |
+ WebInspector.Widget.__assert(child._parentWidget === this, 'Attempt to set non-child widget as default focused.'); |
+ this._defaultFocusedChild = child; |
+ } |
+ |
+ focus() { |
+ if (!this.isShowing()) |
+ return; |
+ |
+ var element = this._defaultFocusedElement; |
+ if (element) { |
+ if (!element.hasFocus()) |
+ element.focus(); |
+ return; |
+ } |
- /** |
- * @return {boolean} |
- */ |
- _hasNonZeroConstraints: function() |
- { |
- var constraints = this.constraints(); |
- return !!(constraints.minimum.width || constraints.minimum.height || constraints.preferred.width || constraints.preferred.height); |
- }, |
- |
- suspendInvalidations() |
- { |
- ++this._invalidationsSuspended; |
- }, |
- |
- resumeInvalidations() |
- { |
- --this._invalidationsSuspended; |
- if (!this._invalidationsSuspended && this._invalidationsRequested) |
- this.invalidateConstraints(); |
- }, |
- |
- invalidateConstraints: function() |
- { |
- if (this._invalidationsSuspended) { |
- this._invalidationsRequested = true; |
- return; |
+ if (this._defaultFocusedChild && this._defaultFocusedChild._visible) { |
+ this._defaultFocusedChild.focus(); |
+ } else { |
+ for (var child of this._children) { |
+ if (child._visible) { |
+ child.focus(); |
+ break; |
} |
- this._invalidationsRequested = false; |
- var cached = this._cachedConstraints; |
- delete this._cachedConstraints; |
- var actual = this.constraints(); |
- if (!actual.isEqual(cached) && this._parentWidget) |
- this._parentWidget.invalidateConstraints(); |
- else |
- this.doLayout(); |
- }, |
- |
- invalidateSize: function() |
- { |
- if (this._parentWidget) |
- this._parentWidget.doLayout(); |
- }, |
- |
- __proto__: WebInspector.Object.prototype |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ hasFocus() { |
+ return this.element.hasFocus(); |
+ } |
+ |
+ /** |
+ * @return {!Size} |
+ */ |
+ measurePreferredSize() { |
+ var document = this.element.ownerDocument; |
+ var oldParent = this.element.parentElement; |
+ var oldNextSibling = this.element.nextSibling; |
+ |
+ WebInspector.Widget._originalAppendChild.call(document.body, this.element); |
+ this.element.positionAt(0, 0); |
+ var result = new Size(this.element.offsetWidth, this.element.offsetHeight); |
+ |
+ this.element.positionAt(undefined, undefined); |
+ if (oldParent) |
+ WebInspector.Widget._originalInsertBefore.call(oldParent, this.element, oldNextSibling); |
+ else |
+ WebInspector.Widget._originalRemoveChild.call(document.body, this.element); |
+ return result; |
+ } |
+ |
+ /** |
+ * @return {!Constraints} |
+ */ |
+ calculateConstraints() { |
+ return new Constraints(); |
+ } |
+ |
+ /** |
+ * @return {!Constraints} |
+ */ |
+ constraints() { |
+ if (typeof this._constraints !== 'undefined') |
+ return this._constraints; |
+ if (typeof this._cachedConstraints === 'undefined') |
+ this._cachedConstraints = this.calculateConstraints(); |
+ return this._cachedConstraints; |
+ } |
+ |
+ /** |
+ * @param {number} width |
+ * @param {number} height |
+ * @param {number} preferredWidth |
+ * @param {number} preferredHeight |
+ */ |
+ setMinimumAndPreferredSizes(width, height, preferredWidth, preferredHeight) { |
+ this._constraints = new Constraints(new Size(width, height), new Size(preferredWidth, preferredHeight)); |
+ this.invalidateConstraints(); |
+ } |
+ |
+ /** |
+ * @param {number} width |
+ * @param {number} height |
+ */ |
+ setMinimumSize(width, height) { |
+ this._constraints = new Constraints(new Size(width, height)); |
+ this.invalidateConstraints(); |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ _hasNonZeroConstraints() { |
+ var constraints = this.constraints(); |
+ return !!( |
+ constraints.minimum.width || constraints.minimum.height || constraints.preferred.width || |
+ constraints.preferred.height); |
+ } |
+ |
+ suspendInvalidations() { |
+ ++this._invalidationsSuspended; |
+ } |
+ |
+ resumeInvalidations() { |
+ --this._invalidationsSuspended; |
+ if (!this._invalidationsSuspended && this._invalidationsRequested) |
+ this.invalidateConstraints(); |
+ } |
+ |
+ invalidateConstraints() { |
+ if (this._invalidationsSuspended) { |
+ this._invalidationsRequested = true; |
+ return; |
+ } |
+ this._invalidationsRequested = false; |
+ var cached = this._cachedConstraints; |
+ delete this._cachedConstraints; |
+ var actual = this.constraints(); |
+ if (!actual.isEqual(cached) && this._parentWidget) |
+ this._parentWidget.invalidateConstraints(); |
+ else |
+ this.doLayout(); |
+ } |
+ |
+ invalidateSize() { |
+ if (this._parentWidget) |
+ this._parentWidget.doLayout(); |
+ } |
}; |
WebInspector.Widget._originalAppendChild = Element.prototype.appendChild; |
@@ -600,175 +598,116 @@ WebInspector.Widget._originalInsertBefore = Element.prototype.insertBefore; |
WebInspector.Widget._originalRemoveChild = Element.prototype.removeChild; |
WebInspector.Widget._originalRemoveChildren = Element.prototype.removeChildren; |
-WebInspector.Widget._incrementWidgetCounter = function(parentElement, childElement) |
-{ |
- var count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0); |
- if (!count) |
- return; |
- |
- while (parentElement) { |
- parentElement.__widgetCounter = (parentElement.__widgetCounter || 0) + count; |
- parentElement = parentElement.parentElementOrShadowHost(); |
- } |
-}; |
- |
-WebInspector.Widget._decrementWidgetCounter = function(parentElement, childElement) |
-{ |
- var count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0); |
- if (!count) |
- return; |
- |
- while (parentElement) { |
- parentElement.__widgetCounter -= count; |
- parentElement = parentElement.parentElementOrShadowHost(); |
- } |
-}; |
- |
-WebInspector.Widget.__assert = function(condition, message) |
-{ |
- if (!condition) { |
- console.trace(); |
- throw new Error(message); |
- } |
-}; |
/** |
- * @param {?Node} node |
+ * @unrestricted |
*/ |
-WebInspector.Widget.focusWidgetForNode = function(node) |
-{ |
- while (node) { |
- if (node.__widget) |
- break; |
- node = node.parentNodeOrShadowHost(); |
- } |
- if (!node) |
- return; |
+WebInspector.VBox = class extends WebInspector.Widget { |
+ /** |
+ * @param {boolean=} isWebComponent |
+ */ |
+ constructor(isWebComponent) { |
+ super(isWebComponent); |
+ this.contentElement.classList.add('vbox'); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {!Constraints} |
+ */ |
+ calculateConstraints() { |
+ var constraints = new Constraints(); |
- var widget = node.__widget; |
- while (widget._parentWidget) { |
- widget._parentWidget._defaultFocusedChild = widget; |
- widget = widget._parentWidget; |
- } |
-}; |
- |
-/** |
- * @constructor |
- * @extends {WebInspector.Widget} |
- * @param {boolean=} isWebComponent |
- */ |
-WebInspector.VBox = function(isWebComponent) |
-{ |
- WebInspector.Widget.call(this, isWebComponent); |
- this.contentElement.classList.add("vbox"); |
-}; |
- |
-WebInspector.VBox.prototype = { |
/** |
- * @override |
- * @return {!Constraints} |
+ * @this {!WebInspector.Widget} |
+ * @suppressReceiverCheck |
*/ |
- calculateConstraints: function() |
- { |
- var constraints = new Constraints(); |
- |
- /** |
- * @this {!WebInspector.Widget} |
- * @suppressReceiverCheck |
- */ |
- function updateForChild() |
- { |
- var child = this.constraints(); |
- constraints = constraints.widthToMax(child); |
- constraints = constraints.addHeight(child); |
- } |
- |
- this._callOnVisibleChildren(updateForChild); |
- return constraints; |
- }, |
+ function updateForChild() { |
+ var child = this.constraints(); |
+ constraints = constraints.widthToMax(child); |
+ constraints = constraints.addHeight(child); |
+ } |
- __proto__: WebInspector.Widget.prototype |
+ this._callOnVisibleChildren(updateForChild); |
+ return constraints; |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.Widget} |
- * @param {boolean=} isWebComponent |
+ * @unrestricted |
*/ |
-WebInspector.HBox = function(isWebComponent) |
-{ |
- WebInspector.Widget.call(this, isWebComponent); |
- this.contentElement.classList.add("hbox"); |
-}; |
+WebInspector.HBox = class extends WebInspector.Widget { |
+ /** |
+ * @param {boolean=} isWebComponent |
+ */ |
+ constructor(isWebComponent) { |
+ super(isWebComponent); |
+ this.contentElement.classList.add('hbox'); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {!Constraints} |
+ */ |
+ calculateConstraints() { |
+ var constraints = new Constraints(); |
-WebInspector.HBox.prototype = { |
/** |
- * @override |
- * @return {!Constraints} |
+ * @this {!WebInspector.Widget} |
+ * @suppressReceiverCheck |
*/ |
- calculateConstraints: function() |
- { |
- var constraints = new Constraints(); |
- |
- /** |
- * @this {!WebInspector.Widget} |
- * @suppressReceiverCheck |
- */ |
- function updateForChild() |
- { |
- var child = this.constraints(); |
- constraints = constraints.addWidth(child); |
- constraints = constraints.heightToMax(child); |
- } |
- |
- this._callOnVisibleChildren(updateForChild); |
- return constraints; |
- }, |
+ function updateForChild() { |
+ var child = this.constraints(); |
+ constraints = constraints.addWidth(child); |
+ constraints = constraints.heightToMax(child); |
+ } |
- __proto__: WebInspector.Widget.prototype |
+ this._callOnVisibleChildren(updateForChild); |
+ return constraints; |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.VBox} |
- * @param {function()} resizeCallback |
+ * @unrestricted |
*/ |
-WebInspector.VBoxWithResizeCallback = function(resizeCallback) |
-{ |
- WebInspector.VBox.call(this); |
+WebInspector.VBoxWithResizeCallback = class extends WebInspector.VBox { |
+ /** |
+ * @param {function()} resizeCallback |
+ */ |
+ constructor(resizeCallback) { |
+ super(); |
this._resizeCallback = resizeCallback; |
-}; |
- |
-WebInspector.VBoxWithResizeCallback.prototype = { |
- onResize: function() |
- { |
- this._resizeCallback(); |
- }, |
- |
- __proto__: WebInspector.VBox.prototype |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onResize() { |
+ this._resizeCallback(); |
+ } |
}; |
/** |
- * @param {!WebInspector.Widget} widget |
- * @constructor |
+ * @unrestricted |
*/ |
-WebInspector.WidgetFocusRestorer = function(widget) |
-{ |
+WebInspector.WidgetFocusRestorer = class { |
+ /** |
+ * @param {!WebInspector.Widget} widget |
+ */ |
+ constructor(widget) { |
this._widget = widget; |
this._previous = widget.element.ownerDocument.deepActiveElement(); |
widget.focus(); |
-}; |
- |
-WebInspector.WidgetFocusRestorer.prototype = { |
- restore: function() |
- { |
- if (!this._widget) |
- return; |
- if (this._widget.hasFocus() && this._previous) |
- this._previous.focus(); |
- this._previous = null; |
- this._widget = null; |
- } |
+ } |
+ |
+ restore() { |
+ if (!this._widget) |
+ return; |
+ if (this._widget.hasFocus() && this._previous) |
+ this._previous.focus(); |
+ this._previous = null; |
+ this._widget = null; |
+ } |
}; |
/** |
@@ -777,10 +716,10 @@ WebInspector.WidgetFocusRestorer.prototype = { |
* @return {?Node} |
* @suppress {duplicate} |
*/ |
-Element.prototype.appendChild = function(child) |
-{ |
- WebInspector.Widget.__assert(!child.__widget || child.parentElement === this, "Attempt to add widget via regular DOM operation."); |
- return WebInspector.Widget._originalAppendChild.call(this, child); |
+Element.prototype.appendChild = function(child) { |
+ WebInspector.Widget.__assert( |
+ !child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.'); |
+ return WebInspector.Widget._originalAppendChild.call(this, child); |
}; |
/** |
@@ -790,10 +729,10 @@ Element.prototype.appendChild = function(child) |
* @return {!Node} |
* @suppress {duplicate} |
*/ |
-Element.prototype.insertBefore = function(child, anchor) |
-{ |
- WebInspector.Widget.__assert(!child.__widget || child.parentElement === this, "Attempt to add widget via regular DOM operation."); |
- return WebInspector.Widget._originalInsertBefore.call(this, child, anchor); |
+Element.prototype.insertBefore = function(child, anchor) { |
+ WebInspector.Widget.__assert( |
+ !child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.'); |
+ return WebInspector.Widget._originalInsertBefore.call(this, child, anchor); |
}; |
/** |
@@ -802,14 +741,15 @@ Element.prototype.insertBefore = function(child, anchor) |
* @return {!Node} |
* @suppress {duplicate} |
*/ |
-Element.prototype.removeChild = function(child) |
-{ |
- WebInspector.Widget.__assert(!child.__widgetCounter && !child.__widget, "Attempt to remove element containing widget via regular DOM operation"); |
- return WebInspector.Widget._originalRemoveChild.call(this, child); |
+Element.prototype.removeChild = function(child) { |
+ WebInspector.Widget.__assert( |
+ !child.__widgetCounter && !child.__widget, |
+ 'Attempt to remove element containing widget via regular DOM operation'); |
+ return WebInspector.Widget._originalRemoveChild.call(this, child); |
}; |
-Element.prototype.removeChildren = function() |
-{ |
- WebInspector.Widget.__assert(!this.__widgetCounter, "Attempt to remove element containing widget via regular DOM operation"); |
- WebInspector.Widget._originalRemoveChildren.call(this); |
+Element.prototype.removeChildren = function() { |
+ WebInspector.Widget.__assert( |
+ !this.__widgetCounter, 'Attempt to remove element containing widget via regular DOM operation'); |
+ WebInspector.Widget._originalRemoveChildren.call(this); |
}; |