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