1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 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/base.html">
9<link rel="import" href="/tracing/model/event_set.html">
10<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
11<link rel="import" href="/tracing/ui/analysis/multi_event_summary.html">
12<link rel="import" href="/tracing/ui/base/table.html">
13<link rel="import" href="/tracing/value/ui/scalar_span.html">
14<link rel="import" href="/tracing/value/unit.html">
15
16<polymer-element name='tr-ui-a-multi-event-details-table'>
17  <template>
18    <style>
19    :host {
20      display: flex;
21      flex-direction: column;
22    }
23    #table {
24      flex: 1 1 auto;
25      align-self: stretch;
26    }
27
28    #titletable {
29      font-weight: bold;
30    }
31
32    #title-info {
33      font-size: 12px;
34    }
35    </style>
36    <tr-ui-b-table id="titletable">
37    </tr-ui-b-table>
38    <tr-ui-b-table id="table">
39    </tr-ui-b-table>
40  </template>
41
42  <script>
43  'use strict';
44
45  Polymer({
46    created: function() {
47      this.selection_ = undefined;
48      this.eventsHaveDuration_ = true;
49      this.eventsHaveSubRows_ = true;
50    },
51
52    ready: function() {
53      this.initTitleTable_();
54    },
55
56    get eventsHaveDuration() {
57      return this.eventsHaveDuration_;
58    },
59
60    set eventsHaveDuration(eventsHaveDuration) {
61      this.eventsHaveDuration_ = eventsHaveDuration;
62      this.updateContents_();
63    },
64
65    get eventsHaveSubRows() {
66      return this.eventsHaveSubRows_;
67    },
68
69    set eventsHaveSubRows(eventsHaveSubRows) {
70      this.eventsHaveSubRows_ = eventsHaveSubRows;
71      this.updateContents_();
72    },
73
74    get selection() {
75      return this.selection_;
76    },
77
78    set selection(selection) {
79      this.selection_ = selection;
80      this.updateContents_();
81    },
82
83    updateContents_: function() {
84      var selection = this.selection_;
85
86      this.updateTitleTable_();
87
88      if (this.selection_ === undefined) {
89        this.$.table.tableRows = [];
90        this.$.table.tableFooterRows = [];
91        this.$.table.rebuild();
92        return;
93      }
94
95      var summary = new tr.ui.analysis.MultiEventSummary(
96          'Totals', this.selection_);
97      this.updateColumns_(summary);
98      this.updateRows_(summary);
99      this.$.table.rebuild();
100    },
101
102    initTitleTable_: function() {
103      var table = this.$.titletable;
104
105      table.showHeader = false;
106      table.tableColumns = [
107        {
108          title: 'Title',
109          value: function(row) { return row.title; },
110          width: '350px'
111        },
112        {
113          title: 'Value',
114          width: '100%',
115          value: function(row) {
116            return row.value;
117          }
118        }
119      ];
120    },
121
122    updateTitleTable_: function() {
123      var title;
124      if (this.selection_ && this.selection_.length)
125        title = this.selection_[0].title;
126      else
127        title = '<No selection>';
128
129      var table = this.$.titletable;
130      table.tableRows = [{
131        title: 'Title',
132        value: title
133      }];
134    },
135
136    updateColumns_: function(summary) {
137      var hasCpuData;
138      if (summary.cpuDuration !== undefined)
139        hasCpuData = true;
140      if (summary.cpuSelfTime !== undefined)
141        hasCpuData = true;
142
143      var colWidthPercentage;
144      if (hasCpuData)
145        colWidthPercentage = '20%';
146      else
147        colWidthPercentage = '33.3333%';
148
149      var ownerDocument = this.ownerDocument;
150      var columns = [];
151
152      columns.push({
153        title: 'Start',
154        value: function(row) {
155          if (row.__proto__ === tr.ui.analysis.MultiEventSummary.prototype) {
156            return row.title;
157          }
158
159          var linkEl = document.createElement('tr-ui-a-analysis-link');
160          linkEl.setSelectionAndContent(function() {
161              return new tr.model.EventSet(row.event);
162          });
163          linkEl.appendChild(tr.v.ui.createScalarSpan(row.start, {
164            unit: tr.v.Unit.byName.timeStampInMs,
165            ownerDocument: ownerDocument
166          }));
167          return linkEl;
168        },
169        width: '350px',
170        cmp: function(rowA, rowB) {
171          return rowA.start - rowB.start;
172        }
173      });
174
175      if (this.eventsHaveDuration_) {
176        columns.push({
177          title: 'Wall Duration (ms)',
178          value: function(row) {
179            return tr.v.ui.createScalarSpan(row.duration, {
180              unit: tr.v.Unit.byName.timeDurationInMs,
181              ownerDocument: ownerDocument
182            });
183          },
184          width: '<upated further down>',
185          cmp: function(rowA, rowB) {
186            return rowA.duration - rowB.duration;
187          }
188        });
189      }
190
191      if (this.eventsHaveDuration_ && hasCpuData) {
192        columns.push({
193          title: 'CPU Duration (ms)',
194          value: function(row) {
195            return tr.v.ui.createScalarSpan(row.cpuDuration, {
196              unit: tr.v.Unit.byName.timeDurationInMs,
197              ownerDocument: ownerDocument
198            });
199          },
200          width: '<upated further down>',
201          cmp: function(rowA, rowB) {
202            return rowA.cpuDuration - rowB.cpuDuration;
203          }
204        });
205      }
206
207      if (this.eventsHaveSubRows_ && this.eventsHaveDuration_) {
208        columns.push({
209          title: 'Self time (ms)',
210          value: function(row) {
211            return tr.v.ui.createScalarSpan(row.selfTime, {
212              unit: tr.v.Unit.byName.timeDurationInMs,
213              ownerDocument: ownerDocument
214            });
215          },
216          width: '<upated further down>',
217          cmp: function(rowA, rowB) {
218            return rowA.selfTime - rowB.selfTime;
219          }
220        });
221      }
222
223      if (this.eventsHaveSubRows_ && this.eventsHaveDuration_ && hasCpuData) {
224        columns.push({
225          title: 'CPU Self Time (ms)',
226          value: function(row) {
227            return tr.v.ui.createScalarSpan(row.cpuSelfTime, {
228              unit: tr.v.Unit.byName.timeDurationInMs,
229              ownerDocument: ownerDocument
230            });
231          },
232          width: '<upated further down>',
233          cmp: function(rowA, rowB) {
234            return rowA.cpuSelfTime - rowB.cpuSelfTime;
235          }
236        });
237      }
238
239      var argKeys = tr.b.dictionaryKeys(summary.totalledArgs);
240      argKeys.sort();
241
242      var otherKeys = summary.untotallableArgs.slice(0);
243      otherKeys.sort();
244
245      argKeys.push.apply(argKeys, otherKeys);
246      var keysWithColumns = argKeys.slice(0, 4);
247      var keysInOtherColumn = argKeys.slice(4);
248
249      keysWithColumns.forEach(function(argKey) {
250
251        var hasTotal = summary.totalledArgs[argKey];
252        var colDesc = {
253          title: 'Arg: ' + argKey,
254          value: function(row) {
255            if (row.__proto__ !== tr.ui.analysis.MultiEventSummary.prototype) {
256              var argView =
257                  document.createElement('tr-ui-a-generic-object-view');
258              argView.object = row.args[argKey];
259              return argView;
260            }
261            if (hasTotal)
262              return row.totalledArgs[argKey];
263            return '';
264          },
265          width: '<upated further down>'
266        };
267        if (hasTotal) {
268          colDesc.cmp = function(rowA, rowB) {
269            return rowA.args[argKey] - rowB.args[argKey];
270          };
271        }
272        columns.push(colDesc);
273      });
274
275      if (keysInOtherColumn.length) {
276        columns.push({
277          title: 'Other Args',
278          value: function(row) {
279            if (row.__proto__ === tr.ui.analysis.MultiEventSummary.prototype)
280              return '';
281            var argView =
282                document.createElement('tr-ui-a-generic-object-view');
283            var obj = {};
284            for (var i = 0; i < keysInOtherColumn.length; i++)
285              obj[keysInOtherColumn[i]] = row.args[keysInOtherColumn[i]];
286            argView.object = obj;
287            return argView;
288          },
289          width: '<upated further down>'
290        });
291      }
292
293      var colWidthPercentage;
294      if (columns.length == 1)
295        colWidthPercentage = '100%';
296      else
297        colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
298
299      for (var i = 1; i < columns.length; i++)
300        columns[i].width = colWidthPercentage;
301
302      this.$.table.tableColumns = columns;
303    },
304
305    updateRows_: function(summary) {
306      this.$.table.sortColumnIndex = 0;
307      function Row(event) {
308        this.event = event;
309      }
310      Row.prototype = {
311        get start() { return this.event.start; },
312        get duration() { return this.event.duration; },
313        get cpuDuration() { return this.event.cpuDuration; },
314        get selfTime() { return this.event.selfTime; },
315        get cpuSelfTime() { return this.event.cpuSelfTime; },
316        get args() { return this.event.args; }
317      };
318
319      this.$.table.tableRows = this.selection_.map(function(event) {
320        return new Row(event);
321      });
322      this.$.table.footerRows = [summary];
323    }
324  });
325</script>
326</polymer-element>
327
328
329