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._marginBehavior = UI.GlassPane.MarginBehavior.DefaultMargin; | 29 this._showArrow = false; |
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} behavior | 111 * @param {boolean} showArrow |
112 */ | 112 */ |
113 setMarginBehavior(behavior) { | 113 setShowArrow(showArrow) { |
114 this._marginBehavior = behavior; | 114 this._showArrow = showArrow; |
115 this._arrowElement.classList.toggle('hidden', behavior !== UI.GlassPane.Marg
inBehavior.Arrow); | 115 this._arrowElement.classList.toggle('hidden', !showArrow); |
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('click', this._onMouseDownBound, true); | 126 document.body.addEventListener('mousedown', this._onMouseDownBound, true); |
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('click', this._onMouseDo
wnBound, true); | 136 this.element.ownerDocument.body.removeEventListener('mousedown', this._onMou
seDownBound, 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 showArrow = this._marginBehavior === UI.GlassPane.MarginBehavior.Arrow; | 155 var gutterSize = this._showArrow ? 8 : 3; |
156 var gutterSize = showArrow ? 8 : (this._marginBehavior === UI.GlassPane.Marg
inBehavior.NoMargin ? 0 : 3); | |
157 var scrollbarSize = 14; | 156 var scrollbarSize = 14; |
158 var arrowSize = 10; | 157 var arrowSize = 10; |
159 | 158 |
160 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.
element.ownerDocument)); | 159 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.
element.ownerDocument)); |
161 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { | 160 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { |
162 this.contentElement.positionAt(0, 0); | 161 this.contentElement.positionAt(0, 0); |
163 this.contentElement.style.width = ''; | 162 this.contentElement.style.width = ''; |
164 this.contentElement.style.maxWidth = ''; | 163 this.contentElement.style.maxWidth = ''; |
165 this.contentElement.style.height = ''; | 164 this.contentElement.style.height = ''; |
166 this.contentElement.style.maxHeight = ''; | 165 this.contentElement.style.maxHeight = ''; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 height = Math.min(height, spaceBottom); | 233 height = Math.min(height, spaceBottom); |
235 } | 234 } |
236 this._arrowElement.setIconType('mediumicon-arrow-top'); | 235 this._arrowElement.setIconType('mediumicon-arrow-top'); |
237 this._arrowElement.classList.add('arrow-top'); | 236 this._arrowElement.classList.add('arrow-top'); |
238 arrowY = anchorBox.y + anchorBox.height + gutterSize; | 237 arrowY = anchorBox.y + anchorBox.height + gutterSize; |
239 } | 238 } |
240 | 239 |
241 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth -
width - gutterSize)); | 240 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth -
width - gutterSize)); |
242 if (!enoughHeight) | 241 if (!enoughHeight) |
243 positionX += arrowSize; | 242 positionX += arrowSize; |
244 else if (showArrow && positionX - arrowSize >= gutterSize) | 243 else if (this._showArrow && positionX - arrowSize >= gutterSize) |
245 positionX -= arrowSize; | 244 positionX -= arrowSize; |
246 width = Math.min(width, containerWidth - positionX - gutterSize); | 245 width = Math.min(width, containerWidth - positionX - gutterSize); |
247 if (2 * arrowSize >= width) { | 246 if (2 * arrowSize >= width) { |
248 this._arrowElement.classList.add('arrow-none'); | 247 this._arrowElement.classList.add('arrow-none'); |
249 } else { | 248 } else { |
250 var arrowX = anchorBox.x + Math.min(50, Math.floor(anchorBox.width / 2
)); | 249 var arrowX = anchorBox.x + Math.min(50, Math.floor(anchorBox.width / 2
)); |
251 arrowX = Number.constrain(arrowX, positionX + arrowSize, positionX + w
idth - arrowSize); | 250 arrowX = Number.constrain(arrowX, positionX + arrowSize, positionX + w
idth - arrowSize); |
252 this._arrowElement.positionAt(arrowX, arrowY, container); | 251 this._arrowElement.positionAt(arrowX, arrowY, container); |
253 } | 252 } |
254 } else { | 253 } else { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 width = Math.min(width, spaceRight); | 291 width = Math.min(width, spaceRight); |
293 } | 292 } |
294 this._arrowElement.setIconType('mediumicon-arrow-left'); | 293 this._arrowElement.setIconType('mediumicon-arrow-left'); |
295 this._arrowElement.classList.add('arrow-left'); | 294 this._arrowElement.classList.add('arrow-left'); |
296 arrowX = anchorBox.x + anchorBox.width + gutterSize; | 295 arrowX = anchorBox.x + anchorBox.width + gutterSize; |
297 } | 296 } |
298 | 297 |
299 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight -
height - gutterSize)); | 298 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight -
height - gutterSize)); |
300 if (!enoughWidth) | 299 if (!enoughWidth) |
301 positionY += arrowSize; | 300 positionY += arrowSize; |
302 else if (showArrow && positionY - arrowSize >= gutterSize) | 301 else if (this._showArrow && positionY - arrowSize >= gutterSize) |
303 positionY -= arrowSize; | 302 positionY -= arrowSize; |
304 height = Math.min(height, containerHeight - positionY - gutterSize); | 303 height = Math.min(height, containerHeight - positionY - gutterSize); |
305 if (2 * arrowSize >= height) { | 304 if (2 * arrowSize >= height) { |
306 this._arrowElement.classList.add('arrow-none'); | 305 this._arrowElement.classList.add('arrow-none'); |
307 } else { | 306 } else { |
308 var arrowY = anchorBox.y + Math.min(50, Math.floor(anchorBox.height /
2)); | 307 var arrowY = anchorBox.y + Math.min(50, Math.floor(anchorBox.height /
2)); |
309 arrowY = Number.constrain(arrowY, positionY + arrowSize, positionY + h
eight - arrowSize); | 308 arrowY = Number.constrain(arrowY, positionY + arrowSize, positionY + h
eight - arrowSize); |
310 this._arrowElement.positionAt(arrowX, arrowY, container); | 309 this._arrowElement.positionAt(arrowX, arrowY, container); |
311 } | 310 } |
312 } | 311 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 | 374 |
376 /** | 375 /** |
377 * @enum {symbol} | 376 * @enum {symbol} |
378 */ | 377 */ |
379 UI.GlassPane.SizeBehavior = { | 378 UI.GlassPane.SizeBehavior = { |
380 SetExactSize: Symbol('SetExactSize'), | 379 SetExactSize: Symbol('SetExactSize'), |
381 SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'), | 380 SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'), |
382 MeasureContent: Symbol('MeasureContent') | 381 MeasureContent: Symbol('MeasureContent') |
383 }; | 382 }; |
384 | 383 |
385 /** | |
386 * @enum {symbol} | |
387 */ | |
388 UI.GlassPane.MarginBehavior = { | |
389 Arrow: Symbol('Arrow'), | |
390 DefaultMargin: Symbol('DefaultMargin'), | |
391 NoMargin: Symbol('NoMargin') | |
392 }; | |
393 | |
394 /** @type {!Map<!Document, !Element>} */ | 384 /** @type {!Map<!Document, !Element>} */ |
395 UI.GlassPane._containers = new Map(); | 385 UI.GlassPane._containers = new Map(); |
396 /** @type {!Set<!UI.GlassPane>} */ | 386 /** @type {!Set<!UI.GlassPane>} */ |
397 UI.GlassPane._panes = new Set(); | 387 UI.GlassPane._panes = new Set(); |
OLD | NEW |