| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright 2016 The Chromium Authors. All rights reserved. | 3 Copyright 2016 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. | 5 found in the LICENSE file. |
| 6 --> | 6 --> |
| 7 | 7 |
| 8 <link rel="import" href="/tracing/base/timing.html"> | 8 <link rel="import" href="/tracing/base/timing.html"> |
| 9 <link rel="import" href="/tracing/ui/base/table.html"> | 9 <link rel="import" href="/tracing/ui/base/table.html"> |
| 10 <link rel="import" href="/tracing/value/histogram_set.html"> | 10 <link rel="import" href="/tracing/value/histogram_set.html"> |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 Polymer({ | 41 Polymer({ |
| 42 is: 'tr-v-ui-histogram-set-table', | 42 is: 'tr-v-ui-histogram-set-table', |
| 43 | 43 |
| 44 created() { | 44 created() { |
| 45 this.viewState_ = undefined; | 45 this.viewState_ = undefined; |
| 46 this.progress_ = () => Promise.resolve(); | 46 this.progress_ = () => Promise.resolve(); |
| 47 this.nameColumnTitle_ = undefined; | 47 this.nameColumnTitle_ = undefined; |
| 48 this.displayLabels_ = []; | 48 this.displayLabels_ = []; |
| 49 this.histograms_ = undefined; | 49 this.histograms_ = undefined; |
| 50 this.sourceHistograms_ = undefined; | 50 this.sourceHistograms_ = undefined; |
| 51 this.sourceHistogramNames_ = undefined; |
| 51 this.groupedHistograms_ = undefined; | 52 this.groupedHistograms_ = undefined; |
| 52 this.hierarchies_ = undefined; | 53 this.hierarchies_ = undefined; |
| 53 this.tableRows_ = undefined; | 54 this.tableRows_ = undefined; |
| 54 }, | 55 }, |
| 55 | 56 |
| 56 ready() { | 57 ready() { |
| 57 this.$.table.zebra = true; | 58 this.$.table.zebra = true; |
| 58 this.addEventListener('sort-column-changed', | 59 this.addEventListener('sort-column-changed', |
| 59 this.onSortColumnChanged_.bind(this)); | 60 this.onSortColumnChanged_.bind(this)); |
| 60 this.addEventListener('requestSelectionChange', | 61 this.addEventListener('requestSelectionChange', |
| (...skipping 26 matching lines...) Expand all Loading... |
| 87 * @param {!tr.v.HistogramSet} sourceHistograms | 88 * @param {!tr.v.HistogramSet} sourceHistograms |
| 88 * @param {!Array.<string>} displayLabels | 89 * @param {!Array.<string>} displayLabels |
| 89 * @param {function(string, function())=} opt_progress | 90 * @param {function(string, function())=} opt_progress |
| 90 */ | 91 */ |
| 91 async build(histograms, sourceHistograms, displayLabels, opt_progress) { | 92 async build(histograms, sourceHistograms, displayLabels, opt_progress) { |
| 92 this.histograms_ = histograms; | 93 this.histograms_ = histograms; |
| 93 this.sourceHistograms_ = sourceHistograms; | 94 this.sourceHistograms_ = sourceHistograms; |
| 94 this.groupedHistograms_ = undefined; | 95 this.groupedHistograms_ = undefined; |
| 95 this.displayLabels_ = displayLabels; | 96 this.displayLabels_ = displayLabels; |
| 96 | 97 |
| 98 this.sourceHistogramNames_ = new Set(); |
| 99 if (this.histograms_.length !== this.sourceHistograms_.length) { |
| 100 for (const hist of this.sourceHistograms_) { |
| 101 this.sourceHistogramNames_.add(hist.name); |
| 102 } |
| 103 } |
| 104 |
| 97 if (opt_progress !== undefined) this.progress_ = opt_progress; | 105 if (opt_progress !== undefined) this.progress_ = opt_progress; |
| 98 | 106 |
| 99 if (histograms.length === 0) { | 107 if (histograms.length === 0) { |
| 100 throw new Error('histogram-set-table requires non-empty HistogramSet.'); | 108 throw new Error('histogram-set-table requires non-empty HistogramSet.'); |
| 101 } | 109 } |
| 102 | 110 |
| 103 await this.progress_('Building columns...'); | 111 await this.progress_('Building columns...'); |
| 104 this.$.table.tableColumns = [ | 112 this.$.table.tableColumns = [ |
| 105 { | 113 { |
| 106 title: this.buildNameColumnTitle_(), | 114 title: this.buildNameColumnTitle_(), |
| 107 value: row => row.nameCell, | 115 value: row => row.nameCell, |
| 108 cmp: (a, b) => a.compareNames(b), | 116 cmp: (a, b) => a.compareNames(b), |
| 109 } | 117 } |
| 110 ].concat(displayLabels.map(l => this.buildColumn_(l))); | 118 ].concat(displayLabels.map(l => this.buildColumn_(l))); |
| 111 | 119 |
| 112 tr.b.Timing.instant('histogram-set-table', 'columnCount', | 120 tr.b.Timing.instant('histogram-set-table', 'columnCount', |
| 113 this.$.table.tableColumns.length); | 121 this.$.table.tableColumns.length); |
| 114 | 122 |
| 115 // updateContents_() displays its own progress. | 123 // updateContents_() displays its own progress. |
| 116 await this.updateContents_(); | 124 await this.updateContents_(); |
| 117 | 125 |
| 118 // Building some elements requires being able to measure them, which is | 126 // Building some elements requires being able to measure them, which is |
| 119 // impossible until they are displayed. If clients hide this table while | 127 // impossible until they are displayed. If clients hide this table while |
| 120 // it is being built, then they must display it when this event fires. | 128 // it is being built, then they must display it when this event fires. |
| 121 this.fire('display-ready'); | 129 this.fire('display-ready'); |
| 122 | 130 |
| 123 this.progress_ = () => Promise.resolve(); | 131 this.progress_ = () => Promise.resolve(); |
| 124 | 132 |
| 125 this.checkNameColumnOverflow_( | 133 for (const row of |
| 126 tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)); | 134 tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)) { |
| 135 row.nameCell.isSource = this.sourceHistogramNames_.has(row.name); |
| 136 this.checkNameColumnOverflow_(row); |
| 137 } |
| 127 }, | 138 }, |
| 128 | 139 |
| 129 buildNameColumnTitle_() { | 140 buildNameColumnTitle_() { |
| 130 this.nameColumnTitle_ = document.createElement('span'); | 141 this.nameColumnTitle_ = document.createElement('span'); |
| 131 this.nameColumnTitle_.style.display = 'inline-flex'; | 142 this.nameColumnTitle_.style.display = 'inline-flex'; |
| 132 | 143 |
| 133 // Wrap the string in a span instead of using createTextNode() so that the | 144 // Wrap the string in a span instead of using createTextNode() so that the |
| 134 // span can be styled later. | 145 // span can be styled later. |
| 135 const nameEl = document.createElement('span'); | 146 const nameEl = document.createElement('span'); |
| 136 nameEl.textContent = 'Name'; | 147 nameEl.textContent = 'Name'; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 256 |
| 246 // Each name-cell listens to this.viewState for updates to | 257 // Each name-cell listens to this.viewState for updates to |
| 247 // constrainNameColumn. | 258 // constrainNameColumn. |
| 248 // Each table-cell listens to this.viewState for updates to | 259 // Each table-cell listens to this.viewState for updates to |
| 249 // displayStatisticName and referenceDisplayLabel. | 260 // displayStatisticName and referenceDisplayLabel. |
| 250 | 261 |
| 251 if (tableRowsDirty) { | 262 if (tableRowsDirty) { |
| 252 await this.progress_('Building DOM...'); | 263 await this.progress_('Building DOM...'); |
| 253 this.$.table.tableRows = this.tableRows_; | 264 this.$.table.tableRows = this.tableRows_; |
| 254 | 265 |
| 266 for (const row of |
| 267 tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)) { |
| 268 row.nameCell.isSource = this.sourceHistogramNames_.has(row.name); |
| 269 } |
| 270 |
| 255 // Try to restore previous row state. | 271 // Try to restore previous row state. |
| 256 // Wait to do this until after the base table has the new rows so that | 272 // Wait to do this until after the base table has the new rows so that |
| 257 // setExpandedForTableRow doesn't get confused. | 273 // setExpandedForTableRow doesn't get confused. |
| 258 for (const row of this.tableRows_) { | 274 for (const row of this.tableRows_) { |
| 259 const previousState = previousRowStates.get(row.name); | 275 const previousState = previousRowStates.get(row.name); |
| 260 if (!previousState) continue; | 276 if (!previousState) continue; |
| 261 await row.restoreState(previousState); | 277 await row.restoreState(previousState); |
| 262 } | 278 } |
| 263 } | 279 } |
| 264 | 280 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 275 'row' + (event.row.viewState.isExpanded ? 'Expanded' : 'Collapsed')); | 291 'row' + (event.row.viewState.isExpanded ? 'Expanded' : 'Collapsed')); |
| 276 | 292 |
| 277 // When the user expands a row, the table builds subRows' name-cells. | 293 // When the user expands a row, the table builds subRows' name-cells. |
| 278 // If a subRow's name isOverflowing even though none of the top-level rows | 294 // If a subRow's name isOverflowing even though none of the top-level rows |
| 279 // are constrained, show the dots to allow the user to unconstrain the | 295 // are constrained, show the dots to allow the user to unconstrain the |
| 280 // name column. | 296 // name column. |
| 281 // Each name-cell.isOverflowing would force layout if we don't await | 297 // Each name-cell.isOverflowing would force layout if we don't await |
| 282 // animationFrame here, which would be inefficient. | 298 // animationFrame here, which would be inefficient. |
| 283 if (this.nameColumnTitle_.children[1].style.display === 'block') return; | 299 if (this.nameColumnTitle_.children[1].style.display === 'block') return; |
| 284 await tr.b.animationFrame(); | 300 await tr.b.animationFrame(); |
| 285 this.checkNameColumnOverflow_(event.row.subRows); | 301 for (const row of event.row.subRows) { |
| 286 }, | 302 this.checkNameColumnOverflow_(row); |
| 287 | |
| 288 checkNameColumnOverflow_(rows) { | |
| 289 for (const row of rows) { | |
| 290 if (!row.nameCell.isOverflowing) continue; | |
| 291 | |
| 292 const [nameSpan, dots] = this.nameColumnTitle_.children; | |
| 293 dots.style.display = 'block'; | |
| 294 | |
| 295 // Size the span containing 'Name' so that the dots align with the | |
| 296 // ellipses in the name-cells. | |
| 297 const labelWidthPx = tr.v.ui.NAME_COLUMN_WIDTH_PX - | |
| 298 dots.getBoundingClientRect().width; | |
| 299 nameSpan.style.width = labelWidthPx + 'px'; | |
| 300 // TODO(benjhayden): Manage this using polymer. | |
| 301 | |
| 302 return; | |
| 303 } | 303 } |
| 304 }, | 304 }, |
| 305 | 305 |
| 306 checkNameColumnOverflow_(row) { |
| 307 if (!row.nameCell.isOverflowing) return; |
| 308 |
| 309 const [nameSpan, dots] = this.nameColumnTitle_.children; |
| 310 dots.style.display = 'block'; |
| 311 |
| 312 // Size the span containing 'Name' so that the dots align with the |
| 313 // ellipses in the name-cells. |
| 314 const labelWidthPx = tr.v.ui.NAME_COLUMN_WIDTH_PX - |
| 315 dots.getBoundingClientRect().width; |
| 316 nameSpan.style.width = labelWidthPx + 'px'; |
| 317 }, |
| 318 |
| 306 groupHistograms_() { | 319 groupHistograms_() { |
| 307 const groupings = this.viewState.groupings.slice(); | 320 const groupings = this.viewState.groupings.slice(); |
| 308 groupings.push(tr.v.HistogramGrouping.DISPLAY_LABEL); | 321 groupings.push(tr.v.HistogramGrouping.DISPLAY_LABEL); |
| 309 | 322 |
| 310 function canSkipGrouping(grouping, groupedHistograms) { | 323 function canSkipGrouping(grouping, groupedHistograms) { |
| 311 // Never skip meaningful groupings. | 324 // Never skip meaningful groupings. |
| 312 if (groupedHistograms.size > 1) return false; | 325 if (groupedHistograms.size > 1) return false; |
| 313 | 326 |
| 314 // Never skip the zero-th grouping. | 327 // Never skip the zero-th grouping. |
| 315 if (grouping.key === groupings[0].key) return false; | 328 if (grouping.key === groupings[0].key) return false; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 444 } |
| 432 return histograms; | 445 return histograms; |
| 433 } | 446 } |
| 434 }); | 447 }); |
| 435 | 448 |
| 436 return { | 449 return { |
| 437 MIDLINE_HORIZONTAL_ELLIPSIS, | 450 MIDLINE_HORIZONTAL_ELLIPSIS, |
| 438 }; | 451 }; |
| 439 }); | 452 }); |
| 440 </script> | 453 </script> |
| OLD | NEW |