analysis_view.html revision 972bd9a9d2c6597a0145a675cbfa527d0510b048
1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/base/iteration_helpers.html"> 9<link rel="import" href="/tracing/model/event_set.html"> 10<link rel="import" href="/tracing/ui/analysis/tab_view.html"> 11<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html"> 12 13<!-- Sub Views. --> 14<link rel="import" href="/tracing/ui/analysis/single_thread_slice_sub_view.html"> 15<link rel="import" href="/tracing/ui/analysis/multi_thread_slice_sub_view.html"> 16 17<link rel="import" href="/tracing/ui/analysis/single_async_slice_sub_view.html"> 18<link rel="import" href="/tracing/ui/analysis/multi_async_slice_sub_view.html"> 19 20<link rel="import" href="/tracing/ui/analysis/single_cpu_slice_sub_view.html"> 21<link rel="import" href="/tracing/ui/analysis/multi_cpu_slice_sub_view.html"> 22 23<link rel="import" href="/tracing/ui/analysis/single_thread_time_slice_sub_view.html"> 24<link rel="import" href="/tracing/ui/analysis/multi_thread_time_slice_sub_view.html"> 25 26<link rel="import" href="/tracing/ui/analysis/single_instant_event_sub_view.html"> 27<link rel="import" href="/tracing/ui/analysis/multi_instant_event_sub_view.html"> 28 29<link rel="import" href="/tracing/ui/analysis/counter_sample_sub_view.html"> 30 31<link rel="import" href="/tracing/ui/analysis/single_flow_event_sub_view.html"> 32<link rel="import" href="/tracing/ui/analysis/multi_flow_event_sub_view.html"> 33 34<link rel="import" href="/tracing/ui/analysis/single_object_instance_sub_view.html"> 35<link rel="import" href="/tracing/ui/analysis/single_object_snapshot_sub_view.html"> 36<link rel="import" href="/tracing/ui/analysis/multi_object_sub_view.html"> 37 38<link rel="import" href="/tracing/ui/analysis/single_sample_sub_view.html"> 39<link rel="import" href="/tracing/ui/analysis/multi_sample_sub_view.html"> 40 41<link rel="import" 42 href="/tracing/ui/analysis/single_interaction_record_sub_view.html"> 43<link rel="import" 44 href="/tracing/ui/analysis/multi_interaction_record_sub_view.html"> 45 46<link rel="import" href="/tracing/ui/analysis/alert_sub_view.html"> 47 48<link rel="import" 49 href="/tracing/ui/analysis/single_frame_sub_view.html"> 50<link rel="import" 51 href="/tracing/ui/analysis/multi_frame_sub_view.html"> 52 53<link rel="import" 54 href="/tracing/ui/analysis/single_process_memory_dump_sub_view.html"> 55<link rel="import" 56 href="/tracing/ui/analysis/multi_process_memory_dump_sub_view.html"> 57<link rel="import" 58 href="/tracing/ui/analysis/single_global_memory_dump_sub_view.html"> 59<link rel="import" href="/tracing/ui/analysis/multi_global_memory_dump_sub_view.html"> 60 61<link rel="import" href="/tracing/ui/analysis/single_power_sample_sub_view.html"> 62<link rel="import" href="/tracing/ui/analysis/multi_power_sample_sub_view.html"> 63 64<link rel="import" href="/tracing/ui/base/polymer_utils.html"> 65 66<!-- 67@fileoverview A component used to display an analysis of a selection, 68using custom elements specialized for different event types. 69--> 70<polymer-element name="tr-ui-a-analysis-view"> 71 <template> 72 <style> 73 :host { 74 background-color: white; 75 display: flex; 76 flex-direction: column; 77 height: 275px; 78 overflow: auto; 79 } 80 81 :host(.tall-mode) { 82 height: 525px; 83 } 84 85 ::content > * { 86 flex: 1 0 auto; 87 } 88 </style> 89 <content></content> 90 </template> 91 <script> 92 'use strict'; 93 (function() { 94 var EventRegistry = tr.model.EventRegistry; 95 96 Polymer({ 97 ready: function() { 98 this.tabView_ = document.createElement('tr-ui-a-tab-view'); 99 this.tabView_.style.flex = '1 1 auto'; 100 this.appendChild(this.tabView_); 101 this.brushingStateController_ = undefined; 102 this.onSelectedTabChange_ = this.onSelectedTabChange_.bind(this); 103 this.onSelectionChanged_ = this.onSelectionChanged_.bind(this); 104 105 this.lastSeenSelection_ = new tr.model.EventSet(); 106 }, 107 108 set tallMode(value) { 109 if (value) 110 this.classList.add('tall-mode'); 111 else 112 this.classList.remove('tall-mode'); 113 }, 114 115 get tallMode() { 116 return this.classList.contains('tall-mode'); 117 }, 118 119 get tabView() { 120 return this.tabView_; 121 }, 122 123 get brushingStateController() { 124 return this.brushingStateController_; 125 }, 126 127 set brushingStateController(brushingStateController) { 128 if (this.brushingStateController) { 129 this.brushingStateController_.removeEventListener( 130 'change', this.onSelectionChanged_); 131 } 132 this.brushingStateController_ = brushingStateController; 133 if (this.brushingStateController) { 134 this.brushingStateController_.addEventListener( 135 'change', this.onSelectionChanged_); 136 } 137 this.onSelectionChanged_(); 138 }, 139 140 get selection() { 141 return this.brushingStateController_.selection; 142 }, 143 144 onSelectionChanged_: function(e) { 145 var selection = this.brushingStateController_.selection; 146 147 var selectionHasSameValue = this.lastSeenSelection_.equals(selection); 148 this.lastSeenSelection_ = selection; 149 if (selectionHasSameValue) 150 return; 151 152 var lastSelectedTabTagName; 153 var lastSelectedTabTypeName; 154 if (this.tabView_.selectedTab) { 155 lastSelectedTabTagName = this.tabView_.selectedTab.tagName; 156 lastSelectedTabTypeName = this.tabView_.selectedTab._eventTypeName; 157 } 158 159 this.tallMode = false; 160 161 var previouslySelectedTab = this.tabView_.selectedTab; 162 this.tabView_.removeEventListener( 163 'selected-tab-change', this.onSelectedTabChange_); 164 165 var previousSubViews = {}; 166 for (var i = 0; i < this.tabView_.children.length; i++) { 167 var previousSubView = this.tabView_.children[i]; 168 previousSubViews[previousSubView._eventTypeName] = previousSubView; 169 } 170 171 this.tabView_.saveTabStates(); 172 this.tabView_.textContent = ''; 173 if (selection.length == 0) { 174 this.tabView_.tabStripHeadingText = 'Nothing selected. Tap stuff.'; 175 } else if (selection.length == 1) { 176 this.tabView_.tabStripHeadingText = '1 item selected: '; 177 } else { 178 this.tabView_.tabStripHeadingText = selection.length + 179 ' items selected: '; 180 } 181 182 var eventsByBaseTypeName = selection.getEventsOrganizedByBaseType(true); 183 184 var numBaseTypesToAnalyze = tr.b.dictionaryLength(eventsByBaseTypeName); 185 for (var eventTypeName in eventsByBaseTypeName) { 186 var subSelection = eventsByBaseTypeName[eventTypeName]; 187 var subView = this.createSubViewForSelection_( 188 eventTypeName, subSelection, previousSubViews[eventTypeName]); 189 // Store the eventTypeName for future tab restoration. 190 subView._eventTypeName = eventTypeName; 191 this.tabView_.appendChild(subView); 192 193 subView.selection = subSelection; 194 } 195 196 // Restore the tab type that was previously selected. First try by tag 197 // name. 198 var tab; 199 if (lastSelectedTabTagName) 200 tab = this.tabView_.querySelector(lastSelectedTabTagName); 201 202 // If that fails, look for a tab with that typeName. 203 if (!tab && lastSelectedTabTypeName) { 204 var tab = tr.b.findFirstInArray( 205 this.tabView_.children, function(tab) { 206 return tab._eventTypeName === lastSelectedTabTypeName; 207 }); 208 } 209 // If all else fails, pick the first tab. 210 if (!tab) 211 tab = this.tabView_.firstChild; 212 213 this.tabView_.selectedTab = tab; 214 this.onSelectedTabChange_(); 215 216 this.tabView_.addEventListener( 217 'selected-tab-change', this.onSelectedTabChange_); 218 }, 219 220 createSubViewForSelection_: function(eventTypeName, subSelection, 221 previousSubView) { 222 // Find. 223 var eventTypeInfo = EventRegistry.getEventTypeInfoByTypeName( 224 eventTypeName); 225 var singleMode = subSelection.length == 1; 226 var tagName; 227 if (subSelection.length === 1) 228 tagName = eventTypeInfo.metadata.singleViewElementName; 229 else 230 tagName = eventTypeInfo.metadata.multiViewElementName; 231 232 if (!tr.ui.b.getPolymerElementNamed(tagName)) 233 throw new Error('Element not registered: ' + tagName); 234 235 // Create if necessary. 236 var subView; 237 if (previousSubView && 238 previousSubView.tagName === tagName.toUpperCase()) 239 subView = previousSubView; 240 else 241 subView = document.createElement(tagName); 242 243 // Set label. 244 var camelLabel; 245 if (subSelection.length === 1) 246 camelLabel = EventRegistry.getUserFriendlySingularName(eventTypeName); 247 else 248 camelLabel = EventRegistry.getUserFriendlyPluralName(eventTypeName); 249 subView.tabLabel = camelLabel + ' (' + subSelection.length + ')'; 250 251 return subView; 252 }, 253 254 onSelectedTabChange_: function() { 255 var brushingStateController = this.brushingStateController_; 256 if (this.tabView_.selectedTab) { 257 var selectedTab = this.tabView_.selectedTab; 258 this.tallMode = selectedTab.requiresTallView; 259 if (brushingStateController) { 260 var rlth = selectedTab.relatedEventsToHighlight; 261 brushingStateController.changeAnalysisViewRelatedEvents(rlth); 262 } 263 } else { 264 this.tallMode = false; 265 if (brushingStateController) 266 brushingStateController.changeAnalysisViewRelatedEvents(undefined); 267 } 268 } 269 }); 270 })(); 271 </script> 272</polymer-element> 273