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 |