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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/Widget.js

Issue 2168223002: DevTools: keep widgets in widget hierarchy upon hide, split attach/detach cycle from show/hide. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lcean Created 4 years, 5 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2011 Google Inc. All Rights Reserved. 3 * Copyright (C) 2011 Google Inc. All Rights Reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. 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 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 23 matching lines...) Expand all
34 this.contentElement = createElementWithClass("div", "widget"); 34 this.contentElement = createElementWithClass("div", "widget");
35 if (isWebComponent) { 35 if (isWebComponent) {
36 this.element = createElementWithClass("div", "vbox flex-auto"); 36 this.element = createElementWithClass("div", "vbox flex-auto");
37 this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.elem ent); 37 this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.elem ent);
38 this._shadowRoot.appendChild(this.contentElement); 38 this._shadowRoot.appendChild(this.contentElement);
39 } else { 39 } else {
40 this.element = this.contentElement; 40 this.element = this.contentElement;
41 } 41 }
42 this._isWebComponent = isWebComponent; 42 this._isWebComponent = isWebComponent;
43 this.element.__widget = this; 43 this.element.__widget = this;
44 this._visible = true; 44 this._visible = false;
45 this._isRoot = false; 45 this._isRoot = false;
46 this._isShowing = false; 46 this._isShowing = false;
47 this._children = []; 47 this._children = [];
48 this._hideOnDetach = false; 48 this._hideOnDetach = false;
49 this._notificationDepth = 0; 49 this._notificationDepth = 0;
50 this._invalidationsSuspended = 0;
50 } 51 }
51 52
52 WebInspector.Widget.prototype = { 53 WebInspector.Widget.prototype = {
53 markAsRoot: function() 54 markAsRoot: function()
54 { 55 {
55 WebInspector.Widget.__assert(!this.element.parentElement, "Attempt to ma rk as root attached node"); 56 WebInspector.Widget.__assert(!this.element.parentElement, "Attempt to ma rk as root attached node");
56 this._isRoot = true; 57 this._isRoot = true;
57 }, 58 },
58 59
59 /** 60 /**
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 */ 113 */
113 _inNotification: function() 114 _inNotification: function()
114 { 115 {
115 return !!this._notificationDepth || (this._parentWidget && this._parentW idget._inNotification()); 116 return !!this._notificationDepth || (this._parentWidget && this._parentW idget._inNotification());
116 }, 117 },
117 118
118 _parentIsShowing: function() 119 _parentIsShowing: function()
119 { 120 {
120 if (this._isRoot) 121 if (this._isRoot)
121 return true; 122 return true;
122 return this._parentWidget && this._parentWidget.isShowing(); 123 return !!this._parentWidget && this._parentWidget.isShowing();
123 }, 124 },
124 125
125 /** 126 /**
126 * @param {function(this:WebInspector.Widget)} method 127 * @param {function(this:WebInspector.Widget)} method
127 */ 128 */
128 _callOnVisibleChildren: function(method) 129 _callOnVisibleChildren: function(method)
129 { 130 {
130 var copy = this._children.slice(); 131 var copy = this._children.slice();
131 for (var i = 0; i < copy.length; ++i) { 132 for (var i = 0; i < copy.length; ++i) {
132 if (copy[i]._parentWidget === this && copy[i]._visible) 133 if (copy[i]._parentWidget === this && copy[i]._visible)
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 199
199 onResize: function() 200 onResize: function()
200 { 201 {
201 }, 202 },
202 203
203 onLayout: function() 204 onLayout: function()
204 { 205 {
205 }, 206 },
206 207
207 /** 208 /**
208 * @param {?Element} parentElement 209 * @param {!Element} parentElement
209 * @param {?Element=} insertBefore 210 * @param {?Element=} insertBefore
210 */ 211 */
211 show: function(parentElement, insertBefore) 212 show: function(parentElement, insertBefore)
212 { 213 {
213 WebInspector.Widget.__assert(parentElement, "Attempt to attach widget wi th no parent element"); 214 WebInspector.Widget.__assert(parentElement, "Attempt to attach widget wi th no parent element");
214 215
215 // Update widget hierarchy. 216 if (!this._isRoot) {
216 if (this.element.parentElement !== parentElement) { 217 // Update widget hierarchy.
217 if (this.element.parentElement)
218 this.detach();
219
220 var currentParent = parentElement; 218 var currentParent = parentElement;
221 while (currentParent && !currentParent.__widget) 219 while (currentParent && !currentParent.__widget)
222 currentParent = currentParent.parentElementOrShadowHost(); 220 currentParent = currentParent.parentElementOrShadowHost();
223 221 WebInspector.Widget.__assert(currentParent, "Attempt to attach widge t to orphan node");
224 if (currentParent) { 222 this.attach(currentParent.__widget);
225 this._parentWidget = currentParent.__widget;
226 this._parentWidget._children.push(this);
227 this._isRoot = false;
228 } else
229 WebInspector.Widget.__assert(this._isRoot, "Attempt to attach wi dget to orphan node");
230 } else if (this._visible) {
231 return;
232 } 223 }
233 224
225 this.showWidget(parentElement, insertBefore);
226 },
227
228 /**
229 * @param {!WebInspector.Widget} parentWidget
230 */
231 attach: function(parentWidget)
232 {
233 if (parentWidget === this._parentWidget)
234 return;
235 if (this._parentWidget)
236 this.detach();
237 this._parentWidget = parentWidget;
238 this._parentWidget._children.push(this);
239 this._isRoot = false;
240 },
241
242 /**
243 * @param {!Element} parentElement
244 * @param {?Element=} insertBefore
245 */
246 showWidget: function(parentElement, insertBefore)
247 {
248 var currentParent = parentElement;
249 while (currentParent && !currentParent.__widget)
250 currentParent = currentParent.parentElementOrShadowHost();
251
252 if (this._isRoot)
253 WebInspector.Widget.__assert(!currentParent, "Attempt to show root w idget under another widget");
254 else
255 WebInspector.Widget.__assert(currentParent && currentParent.__widget === this._parentWidget, "Attempt to show under node belonging to alien widget") ;
256
257 if (this._visible)
258 return;
234 this._visible = true; 259 this._visible = true;
235 260
236 if (this._parentIsShowing()) 261 if (this._parentIsShowing())
237 this._processWillShow(); 262 this._processWillShow();
238 263
239 this.element.classList.remove("hidden"); 264 this.element.classList.remove("hidden");
240 265
241 // Reparent 266 // Reparent
242 if (this.element.parentElement !== parentElement) { 267 if (this.element.parentElement !== parentElement) {
243 WebInspector.Widget._incrementWidgetCounter(parentElement, this.elem ent); 268 WebInspector.Widget._incrementWidgetCounter(parentElement, this.elem ent);
244 if (insertBefore) 269 if (insertBefore)
245 WebInspector.Widget._originalInsertBefore.call(parentElement, th is.element, insertBefore); 270 WebInspector.Widget._originalInsertBefore.call(parentElement, th is.element, insertBefore);
246 else 271 else
247 WebInspector.Widget._originalAppendChild.call(parentElement, thi s.element); 272 WebInspector.Widget._originalAppendChild.call(parentElement, thi s.element);
248 } 273 }
249 274
250 if (this._parentIsShowing()) 275 if (this._parentIsShowing())
251 this._processWasShown(); 276 this._processWasShown();
252 277
253 if (this._parentWidget && this._hasNonZeroConstraints()) 278 if (this._parentWidget && this._hasNonZeroConstraints())
254 this._parentWidget.invalidateConstraints(); 279 this._parentWidget.invalidateConstraints();
255 else 280 else
256 this._processOnResize(); 281 this._processOnResize();
257 }, 282 },
258 283
284 hideWidget: function()
285 {
286 if (!this._parentWidget)
287 return;
288 this._hideWidget();
289 },
290
259 /** 291 /**
260 * @param {boolean=} overrideHideOnDetach 292 * @param {boolean=} overrideHideOnDetach
261 */ 293 */
262 detach: function(overrideHideOnDetach) 294 _hideWidget: function(overrideHideOnDetach)
263 { 295 {
296 if (!this._visible)
297 return;
298 this._visible = false;
264 var parentElement = this.element.parentElement; 299 var parentElement = this.element.parentElement;
265 if (!parentElement)
266 return;
267 300
268 if (this._parentIsShowing()) 301 if (this._parentIsShowing())
269 this._processWillHide(); 302 this._processWillHide();
270 303
271 if (!overrideHideOnDetach && this.shouldHideOnDetach()) { 304 if (!overrideHideOnDetach && this.shouldHideOnDetach()) {
272 this.element.classList.add("hidden"); 305 this.element.classList.add("hidden");
273 this._visible = false; 306 } else {
274 if (this._parentIsShowing()) 307 // Force legal removal
275 this._processWasHidden(); 308 WebInspector.Widget._decrementWidgetCounter(parentElement, this.elem ent);
276 if (this._parentWidget && this._hasNonZeroConstraints()) 309 WebInspector.Widget._originalRemoveChild.call(parentElement, this.el ement);
277 this._parentWidget.invalidateConstraints();
278 return;
279 } 310 }
280 311
281 // Force legal removal
282 WebInspector.Widget._decrementWidgetCounter(parentElement, this.element) ;
283 WebInspector.Widget._originalRemoveChild.call(parentElement, this.elemen t);
284
285 this._visible = false;
286 if (this._parentIsShowing()) 312 if (this._parentIsShowing())
287 this._processWasHidden(); 313 this._processWasHidden();
314 if (this._parentWidget && this._hasNonZeroConstraints())
315 this._parentWidget.invalidateConstraints();
316 },
317
318 detach: function()
319 {
320 if (!this._parentWidget && !this._isRoot)
321 return;
322
323 if (this._visible)
324 this._hideWidget(true);
288 325
289 // Update widget hierarchy. 326 // Update widget hierarchy.
290 if (this._parentWidget) { 327 if (this._parentWidget) {
291 var childIndex = this._parentWidget._children.indexOf(this); 328 var childIndex = this._parentWidget._children.indexOf(this);
292 WebInspector.Widget.__assert(childIndex >= 0, "Attempt to remove non -child widget"); 329 WebInspector.Widget.__assert(childIndex >= 0, "Attempt to remove non -child widget");
293 this._parentWidget._children.splice(childIndex, 1); 330 this._parentWidget._children.splice(childIndex, 1);
294 this._parentWidget.childWasDetached(this); 331 this._parentWidget.childWasDetached(this);
295 var parent = this._parentWidget; 332 var parent = this._parentWidget;
296 this._parentWidget = null; 333 this._parentWidget = null;
297 if (this._hasNonZeroConstraints()) 334 } else {
298 parent.invalidateConstraints();
299 } else
300 WebInspector.Widget.__assert(this._isRoot, "Removing non-root widget from DOM"); 335 WebInspector.Widget.__assert(this._isRoot, "Removing non-root widget from DOM");
336 }
301 }, 337 },
302 338
303 detachChildWidgets: function() 339 detachChildWidgets: function()
304 { 340 {
305 var children = this._children.slice(); 341 var children = this._children.slice();
306 for (var i = 0; i < children.length; ++i) 342 for (var i = 0; i < children.length; ++i)
307 children[i].detach(); 343 children[i].detach();
308 }, 344 },
309 345
310 /** 346 /**
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 508
473 /** 509 /**
474 * @return {boolean} 510 * @return {boolean}
475 */ 511 */
476 _hasNonZeroConstraints: function() 512 _hasNonZeroConstraints: function()
477 { 513 {
478 var constraints = this.constraints(); 514 var constraints = this.constraints();
479 return !!(constraints.minimum.width || constraints.minimum.height || con straints.preferred.width || constraints.preferred.height); 515 return !!(constraints.minimum.width || constraints.minimum.height || con straints.preferred.width || constraints.preferred.height);
480 }, 516 },
481 517
518 suspendInvalidations()
519 {
520 ++this._invalidationsSuspended;
521 },
522
523 resumeInvalidations()
524 {
525 --this._invalidationsSuspended;
526 if (!this._invalidationsSuspended && this._invalidationsRequested)
527 this.invalidateConstraints();
528 },
529
482 invalidateConstraints: function() 530 invalidateConstraints: function()
483 { 531 {
532 if (this._invalidationsSuspended) {
533 this._invalidationsRequested = true;
534 return;
535 }
536 this._invalidationsRequested = false;
484 var cached = this._cachedConstraints; 537 var cached = this._cachedConstraints;
485 delete this._cachedConstraints; 538 delete this._cachedConstraints;
486 var actual = this.constraints(); 539 var actual = this.constraints();
487 if (!actual.isEqual(cached) && this._parentWidget) 540 if (!actual.isEqual(cached) && this._parentWidget)
488 this._parentWidget.invalidateConstraints(); 541 this._parentWidget.invalidateConstraints();
489 else 542 else
490 this.doLayout(); 543 this.doLayout();
491 }, 544 },
492 545
493 invalidateSize: function() 546 invalidateSize: function()
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 { 805 {
753 WebInspector.Widget.__assert(!child.__widgetCounter && !child.__widget, "Att empt to remove element containing widget via regular DOM operation"); 806 WebInspector.Widget.__assert(!child.__widgetCounter && !child.__widget, "Att empt to remove element containing widget via regular DOM operation");
754 return WebInspector.Widget._originalRemoveChild.call(this, child); 807 return WebInspector.Widget._originalRemoveChild.call(this, child);
755 } 808 }
756 809
757 Element.prototype.removeChildren = function() 810 Element.prototype.removeChildren = function()
758 { 811 {
759 WebInspector.Widget.__assert(!this.__widgetCounter, "Attempt to remove eleme nt containing widget via regular DOM operation"); 812 WebInspector.Widget.__assert(!this.__widgetCounter, "Attempt to remove eleme nt containing widget via regular DOM operation");
760 WebInspector.Widget._originalRemoveChildren.call(this); 813 WebInspector.Widget._originalRemoveChildren.call(this);
761 } 814 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698