Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / timeline_view.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7
8 <link rel="stylesheet" href="/tvcm/ui/common.css">
9 <link rel="stylesheet" href="/tracing/timeline_view.css">
10
11 <link rel="import" href="/tracing/analysis/analysis_view.html">
12 <link rel="import" href="/tracing/analysis/cpu_slice_view.html">
13 <link rel="import" href="/tracing/analysis/thread_time_slice_view.html">
14 <link rel="import" href="/tracing/find_control.html">
15 <link rel="import" href="/tracing/find_controller.html">
16 <link rel="import" href="/tracing/timeline_track_view.html">
17 <link rel="import" href="/tvcm/utils.html">
18 <link rel="import" href="/tvcm/settings.html">
19 <link rel="import" href="/tvcm/ui/dom_helpers.html">
20 <link rel="import" href="/tvcm/ui/overlay.html">
21 <link rel="import" href="/tvcm/ui/drag_handle.html">
22 <link rel="import" href="/tracing/side_panel/input_latency.html">
23 <link rel="import" href="/tracing/side_panel/sampling_summary.html">
24 <link rel="import" href="/tracing/side_panel/time_summary.html">
25 <link rel="import" href="/tracing/side_panel/timeline_view.html">
26
27 <template id="timeline-view-template">
28   <div class="control">
29     <div id="left-controls" class="controls"></div>
30     <div class="title">^_^</div>
31     <div id="right-controls" class="controls"></div>
32   </div>
33   <middle-container>
34     <track-view-container></track-view-container>
35     <x-timeline-view-side-panel-container></x-timeline-view-side-panel-container>
36   </middle-container>
37   <x-drag-handle></x-drag-handle>
38   <tracing-analysis-view id="analysis"></tracing-analysis-view>
39 </template>
40
41 <template id="help-btn-template">
42   <div class="button view-help-button">?</div>
43   <div class="view-help-text">
44     <div class="column left">
45       <h2>Navigation</h2>
46       <div class='pair'>
47         <div class='command'>w/s</div>
48         <div class='action'>Zoom in/out (+shift: faster)</div>
49       </div>
50
51       <div class='pair'>
52         <div class='command'>a/d</div>
53         <div class='action'>Pan left/right (+shift: faster)</div>
54       </div>
55
56       <div class='pair'>
57         <div class='command'>&rarr;/shift-TAB</div>
58         <div class='action'>Select previous event</div>
59       </div>
60
61       <div class='pair'>
62         <div class='command'>&larr;/TAB</div>
63         <div class='action'>Select next event</div>
64       </div>
65
66       <h2>Mouse Controls</h2>
67       <div class='pair'>
68         <div class='command'>click</div>
69         <div class='action'>Select event</div>
70       </div>
71       <div class='pair'>
72         <div class='command'>alt-mousewheel</div>
73         <div class='action'>Zoom in/out</div>
74       </div>
75
76       <h3>
77         <span class='mouse-mode-icon select-mode'></span>
78         Select mode
79       </h3>
80       <div class='pair'>
81         <div class='command'>drag</div>
82         <div class='action'>Box select</div>
83       </div>
84
85       <div class='pair'>
86         <div class='command'>double click</div>
87         <div class='action'>Select all events with same title</div>
88       </div>
89
90       <h3>
91         <span class='mouse-mode-icon pan-mode'></span>
92         Pan mode
93       </h3>
94       <div class='pair'>
95         <div class='command'>drag</div>
96         <div class='action'>Pan the view</div>
97       </div>
98
99       <h3>
100         <span class='mouse-mode-icon zoom-mode'></span>
101         Zoom mode
102       </h3>
103       <div class='pair'>
104         <div class='command'>drag</div>
105         <div class='action'>Zoom in/out by dragging up/down</div>
106       </div>
107
108       <h3>
109         <span class='mouse-mode-icon timing-mode'></span>
110         Timing mode
111       </h3>
112       <div class='pair'>
113         <div class='command'>drag</div>
114         <div class='action'>Create or move markers</div>
115       </div>
116
117       <div class='pair'>
118         <div class='command'>double click</div>
119         <div class='action'>Set marker range to slice</div>
120       </div>
121     </div>
122
123     <div class="column right">
124       <h2>General</h2>
125       <div class='pair'>
126         <div class='command'>1-4</div>
127         <div class='action'>Switch mouse mode</div>
128       </div>
129
130       <div class='pair'>
131         <div class='command'>shift</div>
132         <div class='action'>Hold for temporary select</div>
133       </div>
134
135       <div class='pair'>
136         <div class='command'>space</div>
137         <div class='action'>Hold for temporary pan</div>
138       </div>
139
140       <div class='pair'>
141         <div class='command'><span class='mod'></span></div>
142         <div class='action'>Hold for temporary zoom</div>
143       </div>
144
145       <div class='pair'>
146         <div class='command'>/</div>
147         <div class='action'>Search</div>
148       </div>
149
150       <div class='pair'>
151         <div class='command'>enter</div>
152         <div class='action'>Step through search results</div>
153       </div>
154
155       <div class='pair'>
156         <div class='command'>f</div>
157         <div class='action'>Zoom into selection</div>
158       </div>
159
160       <div class='pair'>
161         <div class='command'>z/0</div>
162         <div class='action'>Reset zoom and pan</div>
163       </div>
164
165       <div class='pair'>
166         <div class='command'>g/G</div>
167         <div class='action'>Toggle 60hz grid</div>
168       </div>
169
170       <div class='pair'>
171         <div class='command'>m</div>
172         <div class='action'>Mark current selection</div>
173       </div>
174
175       <div class='pair'>
176         <div class='command'>?</div>
177         <div class='action'>Show help</div>
178       </div>
179     </div>
180   </div>
181 </template>
182
183 <template id="metadata-btn-template">
184   <div class="button view-metadata-button view-info-button">Metadata</div>
185   <div class="info-button-text metadata-dialog-text"></div>
186 </template>
187
188 <script>
189 'use strict';
190
191 /**
192  * @fileoverview View visualizes TRACE_EVENT events using the
193  * tracing.Timeline component and adds in selection summary and control buttons.
194  */
195 tvcm.exportTo('tracing', function() {
196   var THIS_DOC = document.currentScript.ownerDocument;
197
198   /**
199    * View
200    * @constructor
201    * @extends {HTMLUnknownElement}
202    */
203   var TimelineView = tvcm.ui.define('x-timeline-view');
204
205   TimelineView.prototype = {
206     __proto__: HTMLUnknownElement.prototype,
207
208     decorate: function() {
209       var node = tvcm.instantiateTemplate('#timeline-view-template', THIS_DOC);
210       this.appendChild(node);
211
212       this.titleEl_ = this.querySelector('.title');
213       this.leftControlsEl_ = this.querySelector('#left-controls');
214       this.rightControlsEl_ = this.querySelector('#right-controls');
215       this.timelineViewSidePanelContainer_ = this.querySelector(
216           'x-timeline-view-side-panel-container');
217       this.trackViewContainer_ = this.querySelector('track-view-container');
218
219       tvcm.ui.decorate(this.timelineViewSidePanelContainer_,
220                        tracing.TimelineViewSidePanelContainer);
221
222       this.findCtl_ = new TracingFindControl();
223       this.findCtl_.controller = new tracing.FindController();
224
225       this.rightControls.appendChild(this.createMetadataButton_());
226       this.rightControls.appendChild(this.findCtl_);
227       this.rightControls.appendChild(this.createHelpButton_());
228
229       this.dragEl_ = this.querySelector('x-drag-handle');
230       tvcm.ui.decorate(this.dragEl_, tvcm.ui.DragHandle);
231
232       this.analysisEl_ = this.querySelector('#analysis');
233
234       this.addEventListener('requestSelectionChange',
235                             this.onRequestSelectionChange_.bind(this));
236
237       // Bookkeeping.
238       this.onViewportChanged_ = this.onViewportChanged_.bind(this);
239       this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
240       document.addEventListener('keydown', this.onKeyDown_.bind(this), true);
241       document.addEventListener('keypress', this.onKeypress_.bind(this), true);
242
243       this.dragEl_.target = this.analysisEl_;
244
245       // State management on selection change.
246       this.selections_ = {};
247       window.addEventListener('popstate', this.onPopState_.bind(this));
248     },
249
250     createHelpButton_: function() {
251       var node = tvcm.instantiateTemplate('#help-btn-template', THIS_DOC);
252       var showEl = node.querySelector('.view-help-button');
253       var helpTextEl = node.querySelector('.view-help-text');
254
255       var dlg = new tvcm.ui.Overlay();
256       dlg.title = 'chrome://tracing Help';
257       dlg.classList.add('view-help-overlay');
258       dlg.appendChild(node);
259
260       function onClick(e) {
261         dlg.visible = !dlg.visible;
262
263         var mod = tvcm.isMac ? 'cmd ' : 'ctrl';
264         var spans = helpTextEl.querySelectorAll('span.mod');
265         for (var i = 0; i < spans.length; i++) {
266           spans[i].textContent = mod;
267         }
268
269         // Stop event so it doesn't trigger new click listener on document.
270         e.stopPropagation();
271         return false;
272       }
273       showEl.addEventListener('click', onClick.bind(this));
274
275       return showEl;
276     },
277
278     createMetadataButton_: function() {
279       var node = tvcm.instantiateTemplate('#metadata-btn-template', THIS_DOC);
280       var showEl = node.querySelector('.view-metadata-button');
281       var textEl = node.querySelector('.info-button-text');
282
283       var dlg = new tvcm.ui.Overlay();
284       dlg.title = 'Metadata for trace';
285       dlg.classList.add('view-metadata-overlay');
286       dlg.appendChild(node);
287
288       function onClick(e) {
289         dlg.visible = true;
290
291         var metadataStrings = [];
292
293         var model = this.model;
294         for (var data in model.metadata) {
295           var meta = model.metadata[data];
296           var name = JSON.stringify(meta.name);
297           var value = JSON.stringify(meta.value, undefined, ' ');
298
299           metadataStrings.push(name + ': ' + value);
300         }
301         textEl.textContent = metadataStrings.join('\n');
302
303         e.stopPropagation();
304         return false;
305       }
306       showEl.addEventListener('click', onClick.bind(this));
307
308       function updateVisibility() {
309         showEl.style.display =
310             (this.model && this.model.metadata.length) ? '' : 'none';
311       }
312       var updateVisibility_ = updateVisibility.bind(this);
313       updateVisibility_();
314       this.addEventListener('modelChange', updateVisibility_);
315
316       return showEl;
317     },
318
319     get leftControls() {
320       return this.leftControlsEl_;
321     },
322
323     get rightControls() {
324       return this.rightControlsEl_;
325     },
326
327     get viewTitle() {
328       return this.titleEl_.textContent.substring(
329           this.titleEl_.textContent.length - 2);
330     },
331
332     set viewTitle(text) {
333       if (text === undefined) {
334         this.titleEl_.textContent = '';
335         this.titleEl_.hidden = true;
336         return;
337       }
338       this.titleEl_.hidden = false;
339       this.titleEl_.textContent = text;
340     },
341
342     get model() {
343       if (this.trackView_)
344         return this.trackView_.model;
345       return undefined;
346     },
347
348     set model(model) {
349       var modelInstanceChanged = model != this.model;
350       var modelValid = model && !model.bounds.isEmpty;
351
352       // Remove old trackView if the model has completely changed.
353       if (modelInstanceChanged) {
354         this.trackViewContainer_.textContent = '';
355         if (this.trackView_) {
356           this.trackView_.viewport.removeEventListener(
357               'change', this.onViewportChanged_);
358           this.trackView_.removeEventListener(
359               'selectionChange', this.onSelectionChanged_);
360           this.trackView_.detach();
361           this.trackView_ = undefined;
362           this.findCtl_.controller.trackView = undefined;
363         }
364         this.timelineViewSidePanelContainer_.model = undefined;
365       }
366
367       // Create new trackView if needed.
368       if (modelValid && !this.trackView_) {
369         this.trackView_ = new tracing.TimelineTrackView();
370         this.trackView_.focusElement =
371             this.focusElement_ ? this.focusElement_ : this.parentElement;
372         this.trackViewContainer_.appendChild(this.trackView_);
373         this.findCtl_.controller.timeline = this.trackView_;
374         this.trackView_.addEventListener(
375             'selectionChange', this.onSelectionChanged_);
376         this.trackView_.viewport.addEventListener(
377             'change', this.onViewportChanged_);
378       }
379
380       // Set the model.
381       if (modelValid) {
382         this.trackView_.model = model;
383         this.timelineViewSidePanelContainer_.model = model;
384         this.clearSelectionHistory_();
385       }
386       tvcm.dispatchSimpleEvent(this, 'modelChange');
387
388       // Do things that are selection specific
389       if (modelInstanceChanged) {
390         this.onSelectionChanged_();
391         this.onViewportChanged_();
392       }
393     },
394
395     get timeline() {
396       return this.trackView_;
397     },
398
399     get settings() {
400       if (!this.settings_)
401         this.settings_ = new tvcm.Settings();
402       return this.settings_;
403     },
404
405     /**
406      * Sets the element whose focus state will determine whether
407      * to respond to keybaord input.
408      */
409     set focusElement(value) {
410       this.focusElement_ = value;
411       if (this.trackView_)
412         this.trackView_.focusElement = value;
413     },
414
415     /**
416      * @return {Element} The element whose focused state determines
417      * whether to respond to keyboard inputs.
418      * Defaults to the parent element.
419      */
420     get focusElement() {
421       if (this.focusElement_)
422         return this.focusElement_;
423       return this.parentElement;
424     },
425
426     get listenToKeys_() {
427       if (!tvcm.ui.isElementAttachedToDocument(this))
428         return;
429       if (!this.focusElement_)
430         return true;
431       if (this.focusElement.tabIndex >= 0)
432         return document.activeElement == this.focusElement;
433       return true;
434     },
435
436     onKeyDown_: function(e) {
437       if (!this.listenToKeys_)
438         return;
439
440       if (e.keyCode === 27) { // ESC
441         this.focus();
442         e.preventDefault();
443       }
444     },
445
446     onKeypress_: function(e) {
447       if (!this.listenToKeys_)
448         return;
449
450       if (e.keyCode === '/'.charCodeAt(0)) {
451         if (this.findCtl_.hasFocus())
452           this.focus();
453         else
454           this.findCtl_.focus();
455         e.preventDefault();
456       } else if (e.keyCode === '?'.charCodeAt(0)) {
457         this.querySelector('.view-help-button').click();
458         e.preventDefault();
459       }
460     },
461
462     onSelectionChanged_: function(e) {
463       var oldScrollTop = this.trackViewContainer_.scrollTop;
464
465       var selection = this.trackView_ ?
466           this.trackView_.selectionOfInterest :
467           new tracing.Selection();
468       this.analysisEl_.selection = selection;
469       this.trackViewContainer_.scrollTop = oldScrollTop;
470       this.timelineViewSidePanelContainer_.selection = selection;
471     },
472
473     onRequestSelectionChange_: function(e) {
474       // Save the selection so that when back button is pressed,
475       // it could be retrieved.
476       this.selections_[e.selection.guid] = e.selection;
477       var state = {
478         selection_guid: e.selection.guid
479       };
480       window.history.pushState(state);
481
482       this.trackView_.selection = e.selection;
483       e.stopPropagation();
484     },
485
486     onPopState_: function(e) {
487       if (e.state === null)
488         return;
489
490       var selection = this.selections_[e.state.selection_guid];
491       if (selection)
492         this.trackView_.selection = selection;
493       e.stopPropagation();
494     },
495
496     clearSelectionHistory_: function() {
497       this.selections_ = {};
498     },
499
500     onViewportChanged_: function(e) {
501       var spc = this.timelineViewSidePanelContainer_;
502       if (!this.trackView_) {
503         spc.rangeOfInterest.reset();
504         return;
505       }
506
507       var vr = this.trackView_.viewport.interestRange.asRangeObject();
508       if (!spc.rangeOfInterest.equals(vr))
509         spc.rangeOfInterest = vr;
510     }
511   };
512
513   return {
514     TimelineView: TimelineView
515   };
516 });
517 </script>