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

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

Issue 2157363006: 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 {
214 this.attach(parentElement, insertBefore);
215 this.showWidget();
216 },
217
218 /**
219 * @param {!Element} parentElement
220 * @param {?Element=} insertBefore
221 */
222 attach: function(parentElement, insertBefore)
223 {
213 WebInspector.Widget.__assert(parentElement, "Attempt to attach widget wi th no parent element"); 224 WebInspector.Widget.__assert(parentElement, "Attempt to attach widget wi th no parent element");
214 225
215 // Update widget hierarchy. 226 // Update widget hierarchy.
216 if (this.element.parentElement !== parentElement) { 227 var currentParent = parentElement;
217 if (this.element.parentElement) 228 while (currentParent && !currentParent.__widget)
218 this.detach(); 229 currentParent = currentParent.parentElementOrShadowHost();
230 var newParentWidget = currentParent ? currentParent.__widget : null;
219 231
220 var currentParent = parentElement; 232 if (this._parentWidget && newParentWidget !== this._parentWidget) {
221 while (currentParent && !currentParent.__widget) 233 // Reparent.
222 currentParent = currentParent.parentElementOrShadowHost(); 234 this.detach();
223
224 if (currentParent) {
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 } 235 }
233 236
237 if (newParentWidget) {
238 if (this._parentWidget !== newParentWidget) {
239 this._parentWidget = newParentWidget;
240 this._parentWidget._children.push(this);
241 }
242 this._isRoot = false;
243 } else {
244 WebInspector.Widget.__assert(this._isRoot, "Attempt to attach widget to orphan node");
245 }
246
247 this._parentElement = parentElement;
248 this._insertBeforeElement = insertBefore;
249 },
250
251 showWidget: function()
252 {
253 WebInspector.Widget.__assert(this._parentElement, "Attempt to show detac hed widget");
254 if (this._visible)
255 return;
234 this._visible = true; 256 this._visible = true;
235 257
236 if (this._parentIsShowing()) 258 if (this._parentIsShowing())
237 this._processWillShow(); 259 this._processWillShow();
238 260
239 this.element.classList.remove("hidden"); 261 this.element.classList.remove("hidden");
240 262
241 // Reparent 263 // Reparent
242 if (this.element.parentElement !== parentElement) { 264 if (this.element.parentElement !== this._parentElement) {
243 WebInspector.Widget._incrementWidgetCounter(parentElement, this.elem ent); 265 WebInspector.Widget._incrementWidgetCounter(this._parentElement, thi s.element);
244 if (insertBefore) 266 if (this._insertBeforeElement)
245 WebInspector.Widget._originalInsertBefore.call(parentElement, th is.element, insertBefore); 267 WebInspector.Widget._originalInsertBefore.call(this._parentEleme nt, this.element, this._insertBeforeElement);
246 else 268 else
247 WebInspector.Widget._originalAppendChild.call(parentElement, thi s.element); 269 WebInspector.Widget._originalAppendChild.call(this._parentElemen t, this.element);
248 } 270 }
249 271
250 if (this._parentIsShowing()) 272 if (this._parentIsShowing())
251 this._processWasShown(); 273 this._processWasShown();
252 274
253 if (this._parentWidget && this._hasNonZeroConstraints()) 275 if (this._parentWidget && this._hasNonZeroConstraints())
254 this._parentWidget.invalidateConstraints(); 276 this._parentWidget.invalidateConstraints();
255 else 277 else
256 this._processOnResize(); 278 this._processOnResize();
257 }, 279 },
258 280
281 hideWidget: function()
282 {
283 if (!this._parentWidget)
284 return;
285 this._hideWidget();
286 },
287
259 /** 288 /**
260 * @param {boolean=} overrideHideOnDetach 289 * @param {boolean=} overrideHideOnDetach
261 */ 290 */
262 detach: function(overrideHideOnDetach) 291 _hideWidget: function(overrideHideOnDetach)
263 { 292 {
264 var parentElement = this.element.parentElement; 293 WebInspector.Widget.__assert(this._parentElement, "Attempt to hide detac hed widget");
265 if (!parentElement) 294 if (!this._visible)
266 return; 295 return;
296 this._visible = false;
297 var parentElement = this._parentElement;
267 298
268 if (this._parentIsShowing()) 299 if (this._parentIsShowing())
269 this._processWillHide(); 300 this._processWillHide();
270 301
271 if (!overrideHideOnDetach && this.shouldHideOnDetach()) { 302 if (!overrideHideOnDetach && this.shouldHideOnDetach()) {
272 this.element.classList.add("hidden"); 303 this.element.classList.add("hidden");
273 this._visible = false; 304 } else {
274 if (this._parentIsShowing()) 305 // Force legal removal
275 this._processWasHidden(); 306 WebInspector.Widget._decrementWidgetCounter(parentElement, this.elem ent);
276 if (this._parentWidget && this._hasNonZeroConstraints()) 307 WebInspector.Widget._originalRemoveChild.call(parentElement, this.el ement);
277 this._parentWidget.invalidateConstraints();
278 return;
279 } 308 }
280 309
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()) 310 if (this._parentIsShowing())
287 this._processWasHidden(); 311 this._processWasHidden();
312 if (this._hasNonZeroConstraints())
313 this._parentWidget.invalidateConstraints();
314 },
315
316 detach: function()
317 {
318 if (!this._parentWidget)
319 return;
320
321 if (this._visible)
322 this._hideWidget(true);
288 323
289 // Update widget hierarchy. 324 // Update widget hierarchy.
290 if (this._parentWidget) { 325 if (this._parentWidget) {
291 var childIndex = this._parentWidget._children.indexOf(this); 326 var childIndex = this._parentWidget._children.indexOf(this);
292 WebInspector.Widget.__assert(childIndex >= 0, "Attempt to remove non -child widget"); 327 WebInspector.Widget.__assert(childIndex >= 0, "Attempt to remove non -child widget");
293 this._parentWidget._children.splice(childIndex, 1); 328 this._parentWidget._children.splice(childIndex, 1);
294 this._parentWidget.childWasDetached(this); 329 this._parentWidget.childWasDetached(this);
295 var parent = this._parentWidget; 330 var parent = this._parentWidget;
296 this._parentWidget = null; 331 this._parentWidget = null;
297 if (this._hasNonZeroConstraints()) 332 this._parentElement = null;
298 parent.invalidateConstraints(); 333 this._insertBeforeElement = null;
299 } else 334 } 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