5b574801e38f50d655aeee6eaeedbd6f25c24a60
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / selection.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8  * @fileoverview Code for the viewport.
9  */
10 tvcm.require('tvcm.events');
11 tvcm.require('tvcm.guid');
12 tvcm.require('tvcm.range');
13 tvcm.require('tracing.trace_model.instant_event');
14 tvcm.require('tracing.trace_model.flow_event');
15 tvcm.require('tracing.trace_model');
16
17 tvcm.exportTo('tracing', function() {
18
19   var EVENT_TYPES = [
20     {
21       constructor: tracing.trace_model.Slice,
22       name: 'slice',
23       pluralName: 'slices'
24     },
25     {
26       constructor: tracing.trace_model.InstantEvent,
27       name: 'instantEvent',
28       pluralName: 'instantEvents'
29     },
30     {
31       constructor: tracing.trace_model.CounterSample,
32       name: 'counterSample',
33       pluralName: 'counterSamples'
34     },
35     {
36       constructor: tracing.trace_model.ObjectSnapshot,
37       name: 'objectSnapshot',
38       pluralName: 'objectSnapshots'
39     },
40     {
41       constructor: tracing.trace_model.ObjectInstance,
42       name: 'objectInstance',
43       pluralName: 'objectInstances'
44     },
45     {
46       constructor: tracing.trace_model.Sample,
47       name: 'sample',
48       pluralName: 'samples'
49     },
50     {
51       constructor: tracing.trace_model.FlowEvent,
52       name: 'flowEvent',
53       pluralName: 'flowEvents'
54     }
55   ];
56
57   /**
58    * Represents a selection within a  and its associated set of tracks.
59    * @constructor
60    */
61   function Selection(opt_events) {
62     this.bounds_dirty_ = true;
63     this.bounds_ = new tvcm.Range();
64     this.length_ = 0;
65     this.guid_ = tvcm.GUID.allocate();
66
67     if (opt_events) {
68       for (var i = 0; i < opt_events.length; i++)
69         this.push(opt_events[i]);
70     }
71   }
72   Selection.prototype = {
73     __proto__: Object.prototype,
74
75     get bounds() {
76       if (this.bounds_dirty_) {
77         this.bounds_.reset();
78         for (var i = 0; i < this.length_; i++)
79           this[i].addBoundsToRange(this.bounds_);
80         this.bounds_dirty_ = false;
81       }
82       return this.bounds_;
83     },
84
85     get duration() {
86       if (this.bounds_.isEmpty)
87         return 0;
88       return this.bounds_.max - this.bounds_.min;
89     },
90
91     get length() {
92       return this.length_;
93     },
94
95     get guid() {
96       return this.guid_;
97     },
98
99     clear: function() {
100       for (var i = 0; i < this.length_; ++i)
101         delete this[i];
102       this.length_ = 0;
103       this.bounds_dirty_ = true;
104     },
105
106     push: function(event) {
107       this[this.length_++] = event;
108       this.bounds_dirty_ = true;
109       return event;
110     },
111
112     addSelection: function(selection) {
113       for (var i = 0; i < selection.length; i++)
114         this.push(selection[i]);
115     },
116
117     subSelection: function(index, count) {
118       count = count || 1;
119
120       var selection = new Selection();
121       selection.bounds_dirty_ = true;
122       if (index < 0 || index + count > this.length_)
123         throw new Error('Index out of bounds');
124
125       for (var i = index; i < index + count; i++)
126         selection.push(this[i]);
127
128       return selection;
129     },
130
131     getEventsOrganizedByType: function() {
132       var events = {};
133       EVENT_TYPES.forEach(function(eventType) {
134         events[eventType.pluralName] = new Selection();
135       });
136       for (var i = 0; i < this.length_; i++) {
137         var event = this[i];
138         EVENT_TYPES.forEach(function(eventType) {
139           if (event instanceof eventType.constructor)
140             events[eventType.pluralName].push(event);
141         });
142       }
143       return events;
144     },
145
146     enumEventsOfType: function(type, func) {
147       for (var i = 0; i < this.length_; i++)
148         if (this[i] instanceof type)
149           func(this[i]);
150     },
151
152     map: function(fn) {
153       for (var i = 0; i < this.length_; i++)
154         fn(this[i]);
155     },
156
157     /**
158      * Helper for selection previous or next.
159      * @param {boolean} offset If positive, select one forward (next).
160      *   Else, select previous.
161      *
162      * @param {TimelineViewport} viewport The viewport to use to determine what
163      * is near to the current selection.
164      *
165      * @return {boolean} true if current selection changed.
166      */
167     getShiftedSelection: function(viewport, offset) {
168       var newSelection = new Selection();
169       for (var i = 0; i < this.length_; i++) {
170         var event = this[i];
171
172         var addEventToNewSelection = function(event) {
173         };
174
175         // If this is a flow event, and we have a next/prev item in the chain
176         // then we use that as the item to move too. Otherwise, we let the
177         // normal movement for a slice kick in and use that.
178         if (event instanceof tracing.trace_model.FlowEvent) {
179           if ((offset > 0) && event.nextFlowEvent) {
180             newSelection.push(event.nextFlowEvent);
181             continue;
182           } else if ((offset < 0) && event.previousFlowEvent) {
183             newSelection.push(event.previousFlowEvent);
184             continue;
185           }
186         }
187
188         var track = viewport.trackForEvent(event);
189         track.addItemNearToProvidedEventToSelection(
190             event, offset, newSelection);
191       }
192
193       if (newSelection.length == 0)
194         return undefined;
195       return newSelection;
196     }
197   };
198
199   return {
200     Selection: Selection
201   };
202 });