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

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

Issue 2712063002: [DevTools] Migrate Popover to GlassPane (Closed)
Patch Set: nit Created 3 years, 9 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 // 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');
12 this.element.shadowRoot.appendChild(this._arrowElement);
11 13
12 this.registerRequiredCSS('ui/glassPane.css'); 14 this.registerRequiredCSS('ui/glassPane.css');
13 this.element.classList.add('no-pointer-events'); 15 this.element.classList.add('no-pointer-events');
14 this._onMouseDownBound = this._onMouseDown.bind(this); 16 this._onMouseDownBound = this._onMouseDown.bind(this);
15 /** @type {?function(!Event)} */ 17 /** @type {?function(!Event)} */
16 this._onClickOutsideCallback = null; 18 this._onClickOutsideCallback = null;
17 /** @type {?UI.Size} */ 19 /** @type {?UI.Size} */
18 this._maxSize = null; 20 this._maxSize = null;
19 /** @type {?number} */ 21 /** @type {?number} */
20 this._positionX = null; 22 this._positionX = null;
21 /** @type {?number} */ 23 /** @type {?number} */
22 this._positionY = null; 24 this._positionY = null;
23 /** @type {?AnchorBox} */ 25 /** @type {?AnchorBox} */
24 this._anchorBox = null; 26 this._anchorBox = null;
25 this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop; 27 this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop;
26 this._sizeBehavior = UI.GlassPane.SizeBehavior.SetHeight; 28 this._sizeBehavior = UI.GlassPane.SizeBehavior.SetExactSize;
29 this._showArrow = false;
27 } 30 }
28 31
29 /** 32 /**
30 * @return {boolean} 33 * @return {boolean}
31 */ 34 */
32 isShowing() { 35 isShowing() {
33 return this._widget.isShowing(); 36 return this._widget.isShowing();
34 } 37 }
35 38
36 /** 39 /**
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 101 }
99 102
100 /** 103 /**
101 * @param {!UI.GlassPane.AnchorBehavior} behavior 104 * @param {!UI.GlassPane.AnchorBehavior} behavior
102 */ 105 */
103 setAnchorBehavior(behavior) { 106 setAnchorBehavior(behavior) {
104 this._anchorBehavior = behavior; 107 this._anchorBehavior = behavior;
105 } 108 }
106 109
107 /** 110 /**
111 * @param {boolean} showArrow
112 */
113 setShowArrow(showArrow) {
114 this._showArrow = showArrow;
115 this._arrowElement.classList.toggle('hidden', !showArrow);
116 }
117
118 /**
108 * @param {!Document} document 119 * @param {!Document} document
109 */ 120 */
110 show(document) { 121 show(document) {
111 if (this.isShowing()) 122 if (this.isShowing())
112 return; 123 return;
113 // Deliberately starts with 3000 to hide other z-indexed elements below. 124 // Deliberately starts with 3000 to hide other z-indexed elements below.
114 this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size; 125 this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size;
115 document.body.addEventListener('mousedown', this._onMouseDownBound, true); 126 document.body.addEventListener('mousedown', this._onMouseDownBound, true);
116 this._widget.show(document.body); 127 this._widget.show(document.body);
117 UI.GlassPane._panes.add(this); 128 UI.GlassPane._panes.add(this);
(...skipping 16 matching lines...) Expand all
134 return; 145 return;
135 if (this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.deepEle mentFromPoint()))) 146 if (this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.deepEle mentFromPoint())))
136 return; 147 return;
137 this._onClickOutsideCallback.call(null, event); 148 this._onClickOutsideCallback.call(null, event);
138 } 149 }
139 150
140 _positionContent() { 151 _positionContent() {
141 if (!this.isShowing()) 152 if (!this.isShowing())
142 return; 153 return;
143 154
144 var gutterSize = 5; 155 var gutterSize = this._showArrow ? 6 : 3;
156 var scrollbarSize = 14;
157 var arrowSize = 10;
158
145 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this. element.ownerDocument)); 159 var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this. element.ownerDocument));
146 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { 160 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
147 this.contentElement.positionAt(0, 0); 161 this.contentElement.positionAt(0, 0);
148 this.contentElement.style.width = ''; 162 this.contentElement.style.width = '';
163 this.contentElement.style.maxWidth = '';
149 this.contentElement.style.height = ''; 164 this.contentElement.style.height = '';
150 this.contentElement.style.maxHeight = ''; 165 this.contentElement.style.maxHeight = '';
151 } 166 }
152 167
153 var containerWidth = container.offsetWidth; 168 var containerWidth = container.offsetWidth;
154 var containerHeight = container.offsetHeight; 169 var containerHeight = container.offsetHeight;
155 170
156 var width = containerWidth - gutterSize * 2; 171 var width = containerWidth - gutterSize * 2;
157 var height = containerHeight - gutterSize * 2; 172 var height = containerHeight - gutterSize * 2;
158 var positionX = gutterSize; 173 var positionX = gutterSize;
159 var positionY = gutterSize; 174 var positionY = gutterSize;
160 175
161 if (this._maxSize) { 176 if (this._maxSize) {
162 width = Math.min(width, this._maxSize.width); 177 width = Math.min(width, this._maxSize.width);
163 height = Math.min(height, this._maxSize.height); 178 height = Math.min(height, this._maxSize.height);
164 } 179 }
165 180
181 var measuredWidth = 0;
182 var measuredHeight = 0;
166 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) { 183 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
167 width = Math.min(width, this.contentElement.offsetWidth); 184 measuredWidth = this.contentElement.offsetWidth;
168 height = Math.min(height, this.contentElement.offsetHeight); 185 measuredHeight = this.contentElement.offsetHeight;
186 width = Math.min(width, measuredWidth);
187 height = Math.min(height, measuredHeight);
169 } 188 }
170 189
171 if (this._anchorBox) { 190 if (this._anchorBox) {
172 var anchorBox = this._anchorBox.relativeToElement(container); 191 var anchorBox = this._anchorBox.relativeToElement(container);
173 var behavior = this._anchorBehavior; 192 var behavior = this._anchorBehavior;
193 this._arrowElement.classList.remove('arrow-none', 'arrow-top', 'arrow-bott om', 'arrow-left', 'arrow-right');
174 194
175 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop || behavior === UI. GlassPane.AnchorBehavior.PreferBottom) { 195 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop || behavior === UI. GlassPane.AnchorBehavior.PreferBottom) {
176 var top = anchorBox.y - gutterSize; 196 var top = anchorBox.y - 2 * gutterSize;
177 var bottom = containerHeight - anchorBox.y - anchorBox.height - gutterSi ze; 197 var bottom = containerHeight - anchorBox.y - anchorBox.height - 2 * gutt erSize;
178 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop && top < height & & bottom > top) 198 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop && top < height & & bottom > top)
179 behavior = UI.GlassPane.AnchorBehavior.PreferBottom; 199 behavior = UI.GlassPane.AnchorBehavior.PreferBottom;
180 if (behavior === UI.GlassPane.AnchorBehavior.PreferBottom && bottom < he ight && top > bottom) 200 if (behavior === UI.GlassPane.AnchorBehavior.PreferBottom && bottom < he ight && top > bottom)
181 behavior = UI.GlassPane.AnchorBehavior.PreferTop; 201 behavior = UI.GlassPane.AnchorBehavior.PreferTop;
182 202
203 var arrowY;
204 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop) {
205 positionY = Math.max(gutterSize, anchorBox.y - height - gutterSize);
206 var spaceTop = anchorBox.y - positionY - gutterSize;
207 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
208 if (height < measuredHeight)
209 width += scrollbarSize;
210 if (height > spaceTop)
211 this._arrowElement.classList.add('arrow-none');
212 } else {
213 height = Math.min(height, spaceTop);
214 }
215 this._arrowElement.setIconType('mediumicon-arrow-bottom');
216 this._arrowElement.classList.add('arrow-bottom');
217 arrowY = anchorBox.y - gutterSize;
218 } else {
219 positionY = anchorBox.y + anchorBox.height + gutterSize;
220 var spaceBottom = containerHeight - positionY - gutterSize;
221 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
222 if (height < measuredHeight)
223 width += scrollbarSize;
224 if (height > spaceBottom) {
225 this._arrowElement.classList.add('arrow-none');
226 positionY = containerHeight - gutterSize - height;
227 }
228 } else {
229 height = Math.min(height, spaceBottom);
230 }
231 this._arrowElement.setIconType('mediumicon-arrow-top');
232 this._arrowElement.classList.add('arrow-top');
233 arrowY = anchorBox.y + anchorBox.height + gutterSize;
234 }
235
183 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth - width - gutterSize)); 236 positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth - width - gutterSize));
184 width = Math.min(width, containerWidth - positionX - gutterSize); 237 width = Math.min(width, containerWidth - positionX - gutterSize);
185 if (behavior === UI.GlassPane.AnchorBehavior.PreferTop) { 238 if (2 * arrowSize >= width) {
186 positionY = Math.max(gutterSize, anchorBox.y - height); 239 this._arrowElement.classList.add('arrow-none');
187 height = Math.min(height, anchorBox.y - positionY);
188 } else { 240 } else {
189 positionY = anchorBox.y + anchorBox.height; 241 var arrowX = anchorBox.x + Math.min(50, Math.floor(anchorBox.width / 2 ));
190 height = Math.min(height, containerHeight - positionY - gutterSize); 242 arrowX = Number.constrain(arrowX, positionX + arrowSize, positionX + w idth - arrowSize);
243 this._arrowElement.positionAt(arrowX, arrowY, container);
191 } 244 }
192 } else { 245 } else {
193 var left = anchorBox.x - gutterSize; 246 var left = anchorBox.x - 2 * gutterSize;
194 var right = containerWidth - anchorBox.x - anchorBox.width - gutterSize; 247 var right = containerWidth - anchorBox.x - anchorBox.width - 2 * gutterS ize;
195 if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft && left < width && right > left) 248 if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft && left < width && right > left)
196 behavior = UI.GlassPane.AnchorBehavior.PreferRight; 249 behavior = UI.GlassPane.AnchorBehavior.PreferRight;
197 if (behavior === UI.GlassPane.AnchorBehavior.PreferRight && right < widt h && left > right) 250 if (behavior === UI.GlassPane.AnchorBehavior.PreferRight && right < widt h && left > right)
198 behavior = UI.GlassPane.AnchorBehavior.PreferLeft; 251 behavior = UI.GlassPane.AnchorBehavior.PreferLeft;
199 252
253 var arrowX;
254 if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft) {
255 positionX = Math.max(gutterSize, anchorBox.x - width - gutterSize);
256 var spaceLeft = anchorBox.x - positionX - gutterSize;
257 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
258 if (width < measuredWidth)
259 height += scrollbarSize;
260 if (width > spaceLeft)
261 this._arrowElement.classList.add('arrow-none');
262 } else {
263 width = Math.min(width, spaceLeft);
264 }
265 this._arrowElement.setIconType('mediumicon-arrow-right');
266 this._arrowElement.classList.add('arrow-right');
267 arrowX = anchorBox.x - gutterSize;
268 } else {
269 positionX = anchorBox.x + anchorBox.width + gutterSize;
270 var spaceRight = containerWidth - positionX - gutterSize;
271 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
272 if (width < measuredWidth)
273 height += scrollbarSize;
274 if (width > spaceRight) {
275 this._arrowElement.classList.add('arrow-none');
276 positionX = containerWidth - gutterSize - width;
277 }
278 } else {
279 width = Math.min(width, spaceRight);
280 }
281 this._arrowElement.setIconType('mediumicon-arrow-left');
282 this._arrowElement.classList.add('arrow-left');
283 arrowX = anchorBox.x + anchorBox.width + gutterSize;
284 }
285
200 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight - height - gutterSize)); 286 positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight - height - gutterSize));
201 height = Math.min(height, containerHeight - positionY - gutterSize); 287 height = Math.min(height, containerHeight - positionY - gutterSize);
202 if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft) { 288 if (2 * arrowSize >= height) {
203 positionX = Math.max(gutterSize, anchorBox.x - width); 289 this._arrowElement.classList.add('arrow-none');
204 width = Math.min(width, anchorBox.x - positionX);
205 } else { 290 } else {
206 positionX = anchorBox.x + anchorBox.width; 291 var arrowY = anchorBox.y + Math.min(50, Math.floor(anchorBox.height / 2));
207 width = Math.min(width, containerWidth - positionX - gutterSize); 292 arrowY = Number.constrain(arrowY, positionY + arrowSize, positionY + h eight - arrowSize);
293 this._arrowElement.positionAt(arrowX, arrowY, container);
208 } 294 }
209 } 295 }
210 } else { 296 } else {
211 positionX = this._positionX !== null ? this._positionX : (containerWidth - width) / 2; 297 positionX = this._positionX !== null ? this._positionX : (containerWidth - width) / 2;
212 positionY = this._positionY !== null ? this._positionY : (containerHeight - height) / 2; 298 positionY = this._positionY !== null ? this._positionY : (containerHeight - height) / 2;
213 width = Math.min(width, containerWidth - positionX - gutterSize); 299 width = Math.min(width, containerWidth - positionX - gutterSize);
214 height = Math.min(height, containerHeight - positionY - gutterSize); 300 height = Math.min(height, containerHeight - positionY - gutterSize);
301 this._arrowElement.classList.add('arrow-none');
215 } 302 }
216 303
217 this.contentElement.style.width = width + 'px'; 304 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.SetMaxSize)
218 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.SetMaxHeight) 305 this.contentElement.style.maxWidth = width + 'px';
306 else
307 this.contentElement.style.width = width + 'px';
308
309 if (this._sizeBehavior === UI.GlassPane.SizeBehavior.SetMaxSize ||
310 this._sizeBehavior === UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight)
219 this.contentElement.style.maxHeight = height + 'px'; 311 this.contentElement.style.maxHeight = height + 'px';
220 else 312 else
221 this.contentElement.style.height = height + 'px'; 313 this.contentElement.style.height = height + 'px';
314
315
222 this.contentElement.positionAt(positionX, positionY, container); 316 this.contentElement.positionAt(positionX, positionY, container);
223 this._widget.doResize(); 317 this._widget.doResize();
224 } 318 }
225 319
226 /** 320 /**
227 * @protected 321 * @protected
228 * @return {!UI.Widget} 322 * @return {!UI.Widget}
229 */ 323 */
230 widget() { 324 widget() {
231 return this._widget; 325 return this._widget;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 PreferTop: Symbol('PreferTop'), 359 PreferTop: Symbol('PreferTop'),
266 PreferBottom: Symbol('PreferBottom'), 360 PreferBottom: Symbol('PreferBottom'),
267 PreferLeft: Symbol('PreferLeft'), 361 PreferLeft: Symbol('PreferLeft'),
268 PreferRight: Symbol('PreferRight'), 362 PreferRight: Symbol('PreferRight'),
269 }; 363 };
270 364
271 /** 365 /**
272 * @enum {symbol} 366 * @enum {symbol}
273 */ 367 */
274 UI.GlassPane.SizeBehavior = { 368 UI.GlassPane.SizeBehavior = {
275 SetHeight: Symbol('SetHeight'), 369 SetExactSize: Symbol('SetExactSize'),
276 SetMaxHeight: Symbol('SetMaxHeight'), 370 SetMaxSize: Symbol('SetMaxSize'),
371 SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'),
277 MeasureContent: Symbol('MeasureContent') 372 MeasureContent: Symbol('MeasureContent')
278 }; 373 };
279 374
280 /** @type {!Map<!Document, !Element>} */ 375 /** @type {!Map<!Document, !Element>} */
281 UI.GlassPane._containers = new Map(); 376 UI.GlassPane._containers = new Map();
282 /** @type {!Set<!UI.GlassPane>} */ 377 /** @type {!Set<!UI.GlassPane>} */
283 UI.GlassPane._panes = new Set(); 378 UI.GlassPane._panes = new Set();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698