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

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

Issue 2658383002: [DevTools] Make UI.GlassPane position contentElement for different overlay controls. (Closed)
Patch Set: less layouts Created 3 years, 10 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 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * 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 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 */ 50 */
51 UI.SuggestBox = class { 51 UI.SuggestBox = class {
52 /** 52 /**
53 * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate 53 * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate
54 * @param {number=} maxItemsHeight 54 * @param {number=} maxItemsHeight
55 * @param {boolean=} captureEnter 55 * @param {boolean=} captureEnter
56 */ 56 */
57 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) { 57 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) {
58 this._suggestBoxDelegate = suggestBoxDelegate; 58 this._suggestBoxDelegate = suggestBoxDelegate;
59 this._maxItemsHeight = maxItemsHeight; 59 this._maxItemsHeight = maxItemsHeight;
60 this._captureEnter = captureEnter;
60 this._maybeHideBound = this._maybeHide.bind(this); 61 this._maybeHideBound = this._maybeHide.bind(this);
61 this._hideBound = this.hide.bind(this); 62 this._hideBound = this.hide.bind(this);
62 this._container = createElementWithClass('div', 'suggest-box-container');
63 this._rowHeight = 17; 63 this._rowHeight = 17;
64 this._userInteracted = false;
65 this._userEnteredText = '';
66 this._hideTimeoutId = 0;
67 /** @type {?string} */
68 this._onlyCompletion = null;
69
70 this._overlay = new UI.ModalOverlay();
71 this._overlay.setBlockPointerEvents(false);
72 this._overlay.setAnchorBehavior(UI.ModalOverlay.AnchorBehavior.PreferTop);
73 var container = this._overlay.element.createChild('div');
74 var shadowRoot = UI.createShadowRootWithCoreStyles(container, 'ui/suggestBox .css');
75
64 /** @type {!UI.ListControl<!UI.SuggestBox.Suggestion>} */ 76 /** @type {!UI.ListControl<!UI.SuggestBox.Suggestion>} */
65 this._list = new UI.ListControl(this, UI.ListMode.EqualHeightItems); 77 this._list = new UI.ListControl(this, UI.ListMode.EqualHeightItems);
66 this._element = this._list.element; 78 this._element = this._list.element;
67 this._element.classList.add('suggest-box'); 79 this._element.classList.add('suggest-box');
68 this._container.appendChild(this._element); 80 shadowRoot.appendChild(this._element);
69 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true); 81 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true);
70 this._userInteracted = false;
71 this._captureEnter = captureEnter;
72 this._hasVerticalScroll = false;
73 this._userEnteredText = '';
74
75 /** @type {?UI.SuggestBox.Overlay} */
76 this._overlay = null;
77 /** @type {?AnchorBox} */
78 this._lastAnchorBox = null;
79 this._lastItemCount = 0;
80 this._hideTimeoutId = 0;
81 /** @type {?Element} */
82 this._bodyElement = null;
83 /** @type {?string} */
84 this._onlyCompletion = null;
85 } 82 }
86 83
87 /** 84 /**
88 * @return {boolean} 85 * @return {boolean}
89 */ 86 */
90 visible() { 87 visible() {
91 return !!this._container.parentElement; 88 return this._overlay.visible();
92 } 89 }
93 90
94 /** 91 /**
95 * @param {!AnchorBox} anchorBox 92 * @param {!AnchorBox} anchorBox
96 */ 93 */
97 setPosition(anchorBox) { 94 setPosition(anchorBox) {
98 this._updateBoxPosition(anchorBox, this._list.length()); 95 this._overlay.setAnchorBox(anchorBox);
99 } 96 this._overlay.position();
100
101 /**
102 * @param {!AnchorBox} anchorBox
103 * @param {number} length
104 */
105 _updateBoxPosition(anchorBox, length) {
106 console.assert(this._overlay);
107 if (this._lastAnchorBox && this._lastAnchorBox.equals(anchorBox) && this._la stItemCount === length)
108 return;
109 this._lastItemCount = length;
110 this._lastAnchorBox = anchorBox;
111
112 // Position relative to main DevTools element.
113 var container = UI.Dialog.modalHostView().element;
114 anchorBox = anchorBox.relativeToElement(container);
115 var totalHeight = container.offsetHeight;
116 var aboveHeight = anchorBox.y;
117 var underHeight = totalHeight - anchorBox.y - anchorBox.height;
118
119 this._overlay.setLeftOffset(anchorBox.x);
120
121 var under = underHeight >= aboveHeight;
122 if (under)
123 this._overlay.setVerticalOffset(anchorBox.y + anchorBox.height, true);
124 else
125 this._overlay.setVerticalOffset(totalHeight - anchorBox.y, false);
126
127 var spacer = 6;
128 var maxHeight = Math.min(
129 Math.max(underHeight, aboveHeight) - spacer,
130 this._maxItemsHeight ? this._maxItemsHeight * this._rowHeight : Infinity );
131 var height = this._rowHeight * length;
132 this._hasVerticalScroll = height > maxHeight;
133 this._element.style.height = Math.min(maxHeight, height) + 'px';
134 } 97 }
135 98
136 /** 99 /**
137 * @param {!UI.SuggestBox.Suggestions} items 100 * @param {!UI.SuggestBox.Suggestions} items
138 */ 101 */
139 _updateWidth(items) { 102 _updateMaxSize(items) {
140 if (this._hasVerticalScroll) { 103 var maxWidth = this._maxWidth(items);
141 this._element.style.width = '100vw'; 104 var length = this._maxItemsHeight ? Math.min(this._maxItemsHeight, items.len gth) : items.length;
142 return; 105 var maxHeight = length * this._rowHeight;
143 } 106 this._overlay.setMaxSize(new UI.Size(maxWidth, maxHeight));
107 }
108
109 /**
110 * @param {!UI.SuggestBox.Suggestions} items
111 * @return {number}
112 */
113 _maxWidth(items) {
144 if (!items.length) 114 if (!items.length)
145 return; 115 return 300;
caseq 2017/01/31 21:27:20 please extract to a named constant.
dgozman 2017/01/31 23:39:49 Done.
146 // If there are no scrollbars, set the width to the width of the largest row .
147 var maxItem; 116 var maxItem;
148 var maxLength = -Infinity; 117 var maxLength = -Infinity;
149 for (var i = 0; i < items.length; i++) { 118 for (var i = 0; i < items.length; i++) {
150 var length = items[i].title.length + (items[i].subtitle || '').length; 119 var length = items[i].title.length + (items[i].subtitle || '').length;
151 if (length > maxLength) { 120 if (length > maxLength) {
152 maxLength = length; 121 maxLength = length;
153 maxItem = items[i]; 122 maxItem = items[i];
154 } 123 }
155 } 124 }
156 this._element.style.width = 125 var element = this.createElementForItem(/** @type {!UI.SuggestBox.Suggestion } */ (maxItem));
157 UI.measurePreferredSize( 126 return Math.min(300, UI.measurePreferredSize(element, this._element).width);
158 this.createElementForItem(/** @type {!UI.SuggestBox.Suggestion} */ (maxItem)), this._element)
159 .width +
160 'px';
161 } 127 }
162 128
163 /** 129 /**
164 * @param {!Event} event 130 * @param {!Event} event
165 */ 131 */
166 _onBoxMouseDown(event) { 132 _onBoxMouseDown(event) {
167 if (this._hideTimeoutId) { 133 if (this._hideTimeoutId) {
168 window.clearTimeout(this._hideTimeoutId); 134 window.clearTimeout(this._hideTimeoutId);
169 this._hideTimeoutId = 0; 135 this._hideTimeoutId = 0;
170 } 136 }
171 event.preventDefault(); 137 event.preventDefault();
172 } 138 }
173 139
174 _maybeHide() { 140 _maybeHide() {
175 if (!this._hideTimeoutId) 141 if (!this._hideTimeoutId)
176 this._hideTimeoutId = window.setTimeout(this._hideBound, 0); 142 this._hideTimeoutId = window.setTimeout(this._hideBound, 0);
177 } 143 }
178 144
179 /**
180 * // FIXME: make SuggestBox work for multiple documents.
181 * @suppressGlobalPropertiesCheck
182 */
183 _show() { 145 _show() {
184 if (this.visible()) 146 if (this.visible())
185 return; 147 return;
186 this._bodyElement = document.body; 148 this._overlay.show();
187 this._bodyElement.addEventListener('mousedown', this._maybeHideBound, true); 149 this._overlay.document().body.addEventListener('mousedown', this._maybeHideB ound, true);
188 this._element.ownerDocument.defaultView.addEventListener('resize', this._hid eBound, false); 150 this._overlay.document().defaultView.addEventListener('resize', this._hideBo und, false);
189 this._overlay = new UI.SuggestBox.Overlay();
190 this._overlay.setContentElement(this._container);
191 this._rowHeight = 151 this._rowHeight =
192 UI.measurePreferredSize(this.createElementForItem({title: '1', subtitle: '12'}), this._element).height; 152 UI.measurePreferredSize(this.createElementForItem({title: '1', subtitle: '12'}), this._element).height;
193 } 153 }
194 154
195 hide() { 155 hide() {
196 if (!this.visible()) 156 if (!this.visible())
197 return; 157 return;
198
199 this._userInteracted = false; 158 this._userInteracted = false;
200 this._bodyElement.removeEventListener('mousedown', this._maybeHideBound, tru e); 159 this._overlay.document().body.removeEventListener('mousedown', this._maybeHi deBound, true);
201 this._element.ownerDocument.defaultView.removeEventListener('resize', this._ hideBound, false); 160 this._overlay.document().defaultView.removeEventListener('resize', this._hid eBound, false);
202 this._bodyElement = null; 161 this._overlay.hide();
203 this._container.remove();
204 this._overlay.dispose();
205 this._overlay = null;
206 this._lastAnchorBox = null;
207 } 162 }
208 163
209 /** 164 /**
210 * @param {boolean=} isIntermediateSuggestion 165 * @param {boolean=} isIntermediateSuggestion
211 * @return {boolean} 166 * @return {boolean}
212 */ 167 */
213 _applySuggestion(isIntermediateSuggestion) { 168 _applySuggestion(isIntermediateSuggestion) {
214 if (this._onlyCompletion) { 169 if (this._onlyCompletion) {
215 this._suggestBoxDelegate.applySuggestion(this._onlyCompletion, isIntermedi ateSuggestion); 170 this._suggestBoxDelegate.applySuggestion(this._onlyCompletion, isIntermedi ateSuggestion);
216 return true; 171 return true;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 * @param {boolean} selectHighestPriority 297 * @param {boolean} selectHighestPriority
343 * @param {boolean} canShowForSingleItem 298 * @param {boolean} canShowForSingleItem
344 * @param {string} userEnteredText 299 * @param {string} userEnteredText
345 */ 300 */
346 updateSuggestions(anchorBox, completions, selectHighestPriority, canShowForSin gleItem, userEnteredText) { 301 updateSuggestions(anchorBox, completions, selectHighestPriority, canShowForSin gleItem, userEnteredText) {
347 this._onlyCompletion = null; 302 this._onlyCompletion = null;
348 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { 303 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) {
349 this._userEnteredText = userEnteredText; 304 this._userEnteredText = userEnteredText;
350 305
351 this._show(); 306 this._show();
352 this._updateBoxPosition(anchorBox, completions.length); 307 this._updateMaxSize(completions);
353 this._updateWidth(completions); 308 this._overlay.setAnchorBox(anchorBox);
309 this._overlay.position();
354 this._list.invalidateItemHeight(); 310 this._list.invalidateItemHeight();
355 this._list.replaceAllItems(completions); 311 this._list.replaceAllItems(completions);
356 312
357 if (selectHighestPriority) { 313 if (selectHighestPriority) {
358 var highestPriorityItem = completions[0]; 314 var highestPriorityItem = completions[0];
359 var highestPriority = completions[0].priority || 0; 315 var highestPriority = completions[0].priority || 0;
360 for (var i = 0; i < completions.length; i++) { 316 for (var i = 0; i < completions.length; i++) {
361 var priority = completions[i].priority || 0; 317 var priority = completions[i].priority || 0;
362 if (highestPriority < priority) { 318 if (highestPriority < priority) {
363 highestPriority = priority; 319 highestPriority = priority;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 380
425 /** 381 /**
426 * @typedef {!{title: string, subtitle: (string|undefined), iconType: (string|un defined), priority: (number|undefined), isSecondary: (boolean|undefined)}} 382 * @typedef {!{title: string, subtitle: (string|undefined), iconType: (string|un defined), priority: (number|undefined), isSecondary: (boolean|undefined)}}
427 */ 383 */
428 UI.SuggestBox.Suggestion; 384 UI.SuggestBox.Suggestion;
429 385
430 /** 386 /**
431 * @typedef {!Array<!UI.SuggestBox.Suggestion>} 387 * @typedef {!Array<!UI.SuggestBox.Suggestion>}
432 */ 388 */
433 UI.SuggestBox.Suggestions; 389 UI.SuggestBox.Suggestions;
434
435 UI.SuggestBox.Overlay = class {
436 /**
437 * // FIXME: make SuggestBox work for multiple documents.
438 * @suppressGlobalPropertiesCheck
439 */
440 constructor() {
441 this.element = createElementWithClass('div', 'suggest-box-overlay');
442 var root = UI.createShadowRootWithCoreStyles(this.element, 'ui/suggestBox.cs s');
443 this._leftSpacerElement = root.createChild('div', 'suggest-box-left-spacer') ;
444 this._horizontalElement = root.createChild('div', 'suggest-box-horizontal');
445 this._topSpacerElement = this._horizontalElement.createChild('div', 'suggest -box-top-spacer');
446 this._bottomSpacerElement = this._horizontalElement.createChild('div', 'sugg est-box-bottom-spacer');
447 this._resize();
448 document.body.appendChild(this.element);
449 }
450
451 /**
452 * @param {number} offset
453 */
454 setLeftOffset(offset) {
455 this._leftSpacerElement.style.flexBasis = offset + 'px';
456 }
457
458 /**
459 * @param {number} offset
460 * @param {boolean} isTopOffset
461 */
462 setVerticalOffset(offset, isTopOffset) {
463 this.element.classList.toggle('under-anchor', isTopOffset);
464
465 if (isTopOffset) {
466 this._bottomSpacerElement.style.flexBasis = 'auto';
467 this._topSpacerElement.style.flexBasis = offset + 'px';
468 } else {
469 this._bottomSpacerElement.style.flexBasis = offset + 'px';
470 this._topSpacerElement.style.flexBasis = 'auto';
471 }
472 }
473
474 /**
475 * @param {!Element} element
476 */
477 setContentElement(element) {
478 this._horizontalElement.insertBefore(element, this._bottomSpacerElement);
479 }
480
481 _resize() {
482 var container = UI.Dialog.modalHostView().element;
483 var containerBox = container.boxInWindow(container.ownerDocument.defaultView );
484
485 this.element.style.left = containerBox.x + 'px';
486 this.element.style.top = containerBox.y + 'px';
487 this.element.style.height = containerBox.height + 'px';
488 this.element.style.width = containerBox.width + 'px';
489 }
490
491 dispose() {
492 this.element.remove();
493 }
494 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698