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