Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 UI.GlassPane = class { | 5 UI.GlassPane = class { |
| 6 constructor() { | 6 constructor() { |
| 7 this._widget = new UI.Widget(true); | 7 this._widget = new UI.Widget(true); |
| 8 this._widget.markAsRoot(); | 8 this._widget.markAsRoot(); |
| 9 this.element = this._widget.element; | 9 this.element = this._widget.element; |
| 10 this.contentElement = this._widget.contentElement; | 10 this.contentElement = this._widget.contentElement; |
| 11 this._arrowElement = UI.Icon.create('', 'arrow hidden'); | 11 this._arrowElement = UI.Icon.create('', 'arrow hidden'); |
| 12 this.element.shadowRoot.appendChild(this._arrowElement); | 12 this.element.shadowRoot.appendChild(this._arrowElement); |
| 13 | 13 |
| 14 this.registerRequiredCSS('ui/glassPane.css'); | 14 this.registerRequiredCSS('ui/glassPane.css'); |
| 15 this.element.classList.add('no-pointer-events'); | 15 this.element.classList.add('no-pointer-events'); |
| 16 this._onMouseDownBound = this._onMouseDown.bind(this); | 16 this._onMouseDownBound = this._onMouseDown.bind(this); |
| 17 /** @type {?function(!Event)} */ | 17 /** @type {?function(!Event)} */ |
| 18 this._onClickOutsideCallback = null; | 18 this._onClickOutsideCallback = null; |
| 19 /** @type {?UI.Size} */ | 19 /** @type {?UI.Size} */ |
| 20 this._maxSize = null; | 20 this._maxSize = null; |
| 21 /** @type {?number} */ | 21 /** @type {?number} */ |
| 22 this._positionX = null; | 22 this._positionX = null; |
| 23 /** @type {?number} */ | 23 /** @type {?number} */ |
| 24 this._positionY = null; | 24 this._positionY = null; |
| 25 /** @type {?AnchorBox} */ | 25 /** @type {?AnchorBox} */ |
| 26 this._anchorBox = null; | 26 this._anchorBox = null; |
| 27 this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop; | 27 this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop; |
| 28 this._sizeBehavior = UI.GlassPane.SizeBehavior.SetExactSize; | 28 this._sizeBehavior = UI.GlassPane.SizeBehavior.SetExactSize; |
| 29 this._showArrow = false; | 29 this._marginBehavior = UI.GlassPane.MarginBehavior.DefaultMargin; |
| 30 } | 30 } |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * @return {boolean} | 33 * @return {boolean} |
| 34 */ | 34 */ |
| 35 isShowing() { | 35 isShowing() { |
| 36 return this._widget.isShowing(); | 36 return this._widget.isShowing(); |
| 37 } | 37 } |
| 38 | 38 |
| 39 /** | 39 /** |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 } | 101 } |
| 102 | 102 |
| 103 /** | 103 /** |
| 104 * @param {!UI.GlassPane.AnchorBehavior} behavior | 104 * @param {!UI.GlassPane.AnchorBehavior} behavior |
| 105 */ | 105 */ |
| 106 setAnchorBehavior(behavior) { | 106 setAnchorBehavior(behavior) { |
| 107 this._anchorBehavior = behavior; | 107 this._anchorBehavior = behavior; |
| 108 } | 108 } |
| 109 | 109 |
| 110 /** | 110 /** |
| 111 * @param {boolean} showArrow | 111 * @param {boolean} behavior |
| 112 */ | 112 */ |
| 113 setShowArrow(showArrow) { | 113 setMarginBehavior(behavior) { |
| 114 this._showArrow = showArrow; | 114 this._marginBehavior = behavior; |
| 115 this._arrowElement.classList.toggle('hidden', !showArrow); | 115 this._arrowElement.classList.toggle('hidden', behavior !== UI.GlassPane.Marg inBehavior.Arrow); |
| 116 } | 116 } |
| 117 | 117 |
| 118 /** | 118 /** |
| 119 * @param {!Document} document | 119 * @param {!Document} document |
| 120 */ | 120 */ |
| 121 show(document) { | 121 show(document) { |
| 122 if (this.isShowing()) | 122 if (this.isShowing()) |
| 123 return; | 123 return; |
| 124 // Deliberately starts with 3000 to hide other z-indexed elements below. | 124 // Deliberately starts with 3000 to hide other z-indexed elements below. |
| 125 this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size; | 125 this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size; |
| 126 document.body.addEventListener('mousedown', this._onMouseDownBound, true); | 126 document.body.addEventListener('click', this._onMouseDownBound, true); |
|
lushnikov
2017/03/27 18:08:33
is this change to better replicate softcontextmenu
dgozman
2017/03/27 23:08:08
Yep.
| |
| 127 this._widget.show(document.body); | 127 this._widget.show(document.body); |
| 128 UI.GlassPane._panes.add(this); | 128 UI.GlassPane._panes.add(this); |
| 129 this._positionContent(); | 129 this._positionContent(); |
| 130 } | 130 } |
| 131 | 131 |
| 132 hide() { | 132 hide() { |
| 133 if (!this.isShowing()) | 133 if (!this.isShowing()) |
| 134 return; | 134 return; |
| 135 UI.GlassPane._panes.delete(this); | 135 UI.GlassPane._panes.delete(this); |
| 136 this.element.ownerDocument.body.removeEventListener('mousedown', this._onMou seDownBound, true); | 136 this.element.ownerDocument.body.removeEventListener('click', this._onMouseDo wnBound, true); |
| 137 this._widget.detach(); | 137 this._widget.detach(); |
| 138 } | 138 } |
| 139 | 139 |
| 140 /** | 140 /** |
| 141 * @param {!Event} event | 141 * @param {!Event} event |
| 142 */ | 142 */ |
| 143 _onMouseDown(event) { | 143 _onMouseDown(event) { |
| 144 if (!this._onClickOutsideCallback) | 144 if (!this._onClickOutsideCallback) |
| 145 return; | 145 return; |
| 146 if (this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.deepEle mentFromPoint()))) | 146 if (this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.deepEle mentFromPoint()))) |
| 147 return; | 147 return; |
| 148 this._onClickOutsideCallback.call(null, event); | 148 this._onClickOutsideCallback.call(null, event); |
| 149 } | 149 } |
| 150 | 150 |
| 151 _positionContent() { | 151 _positionContent() { |
| 152 if (!this.isShowing()) | 152 if (!this.isShowing()) |
| 153 return; | 153 return; |
| 154 | 154 |
| 155 var gutterSize = this._showArrow ? 8 : 3; | 155 var showArrow = this._marginBehavior === UI.GlassPane.MarginBehavior.Arrow; |
| 156 var gutterSize = showArrow ? 8 : (this._marginBehavior === UI.GlassPane.Marg inBehavior.NoMargin ? 0 : 3); | |
| 156 var scrollbarSize = 14; | 157 var scrollbarSize = 14; |
| 157 var arrowSize = 10; | 158 var arrowSize = 10; |
| 158 | 159 |
| 159 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this. element.ownerDocument)); | 160 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this. element.ownerDocument)); |
| 160 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { | 161 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { |
| 161 this.contentElement.positionAt(0, 0); | 162 this.contentElement.positionAt(0, 0); |
| 162 this.contentElement.style.width = ''; | 163 this.contentElement.style.width = ''; |
| 163 this.contentElement.style.maxWidth = ''; | 164 this.contentElement.style.maxWidth = ''; |
| 164 this.contentElement.style.height = ''; | 165 this.contentElement.style.height = ''; |
| 165 this.contentElement.style.maxHeight = ''; | 166 this.contentElement.style.maxHeight = ''; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 height = Math.min(height, spaceBottom); | 234 height = Math.min(height, spaceBottom); |
| 234 } | 235 } |
| 235 this._arrowElement.setIconType('mediumicon-arrow-top'); | 236 this._arrowElement.setIconType('mediumicon-arrow-top'); |
| 236 this._arrowElement.classList.add('arrow-top'); | 237 this._arrowElement.classList.add('arrow-top'); |
| 237 arrowY = anchorBox.y + anchorBox.height + gutterSize; | 238 arrowY = anchorBox.y + anchorBox.height + gutterSize; |
| 238 } | 239 } |
| 239 | 240 |
| 240 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth - width - gutterSize)); | 241 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth - width - gutterSize)); |
| 241 if (!enoughHeight) | 242 if (!enoughHeight) |
| 242 positionX += arrowSize; | 243 positionX += arrowSize; |
| 243 else if (this._showArrow && positionX - arrowSize >= gutterSize) | 244 else if (showArrow && positionX - arrowSize >= gutterSize) |
| 244 positionX -= arrowSize; | 245 positionX -= arrowSize; |
| 245 width = Math.min(width, containerWidth - positionX - gutterSize); | 246 width = Math.min(width, containerWidth - positionX - gutterSize); |
| 246 if (2 * arrowSize >= width) { | 247 if (2 * arrowSize >= width) { |
| 247 this._arrowElement.classList.add('arrow-none'); | 248 this._arrowElement.classList.add('arrow-none'); |
| 248 } else { | 249 } else { |
| 249 var arrowX = anchorBox.x + Math.min(50, Math.floor(anchorBox.width / 2 )); | 250 var arrowX = anchorBox.x + Math.min(50, Math.floor(anchorBox.width / 2 )); |
| 250 arrowX = Number.constrain(arrowX, positionX + arrowSize, positionX + w idth - arrowSize); | 251 arrowX = Number.constrain(arrowX, positionX + arrowSize, positionX + w idth - arrowSize); |
| 251 this._arrowElement.positionAt(arrowX, arrowY, container); | 252 this._arrowElement.positionAt(arrowX, arrowY, container); |
| 252 } | 253 } |
| 253 } else { | 254 } else { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 width = Math.min(width, spaceRight); | 292 width = Math.min(width, spaceRight); |
| 292 } | 293 } |
| 293 this._arrowElement.setIconType('mediumicon-arrow-left'); | 294 this._arrowElement.setIconType('mediumicon-arrow-left'); |
| 294 this._arrowElement.classList.add('arrow-left'); | 295 this._arrowElement.classList.add('arrow-left'); |
| 295 arrowX = anchorBox.x + anchorBox.width + gutterSize; | 296 arrowX = anchorBox.x + anchorBox.width + gutterSize; |
| 296 } | 297 } |
| 297 | 298 |
| 298 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight - height - gutterSize)); | 299 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight - height - gutterSize)); |
| 299 if (!enoughWidth) | 300 if (!enoughWidth) |
| 300 positionY += arrowSize; | 301 positionY += arrowSize; |
| 301 else if (this._showArrow && positionY - arrowSize >= gutterSize) | 302 else if (showArrow && positionY - arrowSize >= gutterSize) |
| 302 positionY -= arrowSize; | 303 positionY -= arrowSize; |
| 303 height = Math.min(height, containerHeight - positionY - gutterSize); | 304 height = Math.min(height, containerHeight - positionY - gutterSize); |
| 304 if (2 * arrowSize >= height) { | 305 if (2 * arrowSize >= height) { |
| 305 this._arrowElement.classList.add('arrow-none'); | 306 this._arrowElement.classList.add('arrow-none'); |
| 306 } else { | 307 } else { |
| 307 var arrowY = anchorBox.y + Math.min(50, Math.floor(anchorBox.height / 2)); | 308 var arrowY = anchorBox.y + Math.min(50, Math.floor(anchorBox.height / 2)); |
| 308 arrowY = Number.constrain(arrowY, positionY + arrowSize, positionY + h eight - arrowSize); | 309 arrowY = Number.constrain(arrowY, positionY + arrowSize, positionY + h eight - arrowSize); |
| 309 this._arrowElement.positionAt(arrowX, arrowY, container); | 310 this._arrowElement.positionAt(arrowX, arrowY, container); |
| 310 } | 311 } |
| 311 } | 312 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 | 375 |
| 375 /** | 376 /** |
| 376 * @enum {symbol} | 377 * @enum {symbol} |
| 377 */ | 378 */ |
| 378 UI.GlassPane.SizeBehavior = { | 379 UI.GlassPane.SizeBehavior = { |
| 379 SetExactSize: Symbol('SetExactSize'), | 380 SetExactSize: Symbol('SetExactSize'), |
| 380 SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'), | 381 SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'), |
| 381 MeasureContent: Symbol('MeasureContent') | 382 MeasureContent: Symbol('MeasureContent') |
| 382 }; | 383 }; |
| 383 | 384 |
| 385 /** | |
| 386 * @enum {symbol} | |
| 387 */ | |
| 388 UI.GlassPane.MarginBehavior = { | |
| 389 Arrow: Symbol('Arrow'), | |
| 390 DefaultMargin: Symbol('DefaultMargin'), | |
| 391 NoMargin: Symbol('NoMargin') | |
| 392 }; | |
| 393 | |
| 384 /** @type {!Map<!Document, !Element>} */ | 394 /** @type {!Map<!Document, !Element>} */ |
| 385 UI.GlassPane._containers = new Map(); | 395 UI.GlassPane._containers = new Map(); |
| 386 /** @type {!Set<!UI.GlassPane>} */ | 396 /** @type {!Set<!UI.GlassPane>} */ |
| 387 UI.GlassPane._panes = new Set(); | 397 UI.GlassPane._panes = new Set(); |
| OLD | NEW |