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.
8 * @fileoverview Code for the viewport.
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');
17 tvcm.exportTo('tracing', function() {
21 constructor: tracing.trace_model.Slice,
26 constructor: tracing.trace_model.InstantEvent,
28 pluralName: 'instantEvents'
31 constructor: tracing.trace_model.CounterSample,
32 name: 'counterSample',
33 pluralName: 'counterSamples'
36 constructor: tracing.trace_model.ObjectSnapshot,
37 name: 'objectSnapshot',
38 pluralName: 'objectSnapshots'
41 constructor: tracing.trace_model.ObjectInstance,
42 name: 'objectInstance',
43 pluralName: 'objectInstances'
46 constructor: tracing.trace_model.Sample,
51 constructor: tracing.trace_model.FlowEvent,
53 pluralName: 'flowEvents'
58 * Represents a selection within a and its associated set of tracks.
61 function Selection(opt_events) {
62 this.bounds_dirty_ = true;
63 this.bounds_ = new tvcm.Range();
65 this.guid_ = tvcm.GUID.allocate();
68 for (var i = 0; i < opt_events.length; i++)
69 this.push(opt_events[i]);
72 Selection.prototype = {
73 __proto__: Object.prototype,
76 if (this.bounds_dirty_) {
78 for (var i = 0; i < this.length_; i++)
79 this[i].addBoundsToRange(this.bounds_);
80 this.bounds_dirty_ = false;
86 if (this.bounds_.isEmpty)
88 return this.bounds_.max - this.bounds_.min;
100 for (var i = 0; i < this.length_; ++i)
103 this.bounds_dirty_ = true;
106 push: function(event) {
107 this[this.length_++] = event;
108 this.bounds_dirty_ = true;
112 addSelection: function(selection) {
113 for (var i = 0; i < selection.length; i++)
114 this.push(selection[i]);
117 subSelection: function(index, count) {
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');
125 for (var i = index; i < index + count; i++)
126 selection.push(this[i]);
131 getEventsOrganizedByType: function() {
133 EVENT_TYPES.forEach(function(eventType) {
134 events[eventType.pluralName] = new Selection();
136 for (var i = 0; i < this.length_; i++) {
138 EVENT_TYPES.forEach(function(eventType) {
139 if (event instanceof eventType.constructor)
140 events[eventType.pluralName].push(event);
146 enumEventsOfType: function(type, func) {
147 for (var i = 0; i < this.length_; i++)
148 if (this[i] instanceof type)
153 for (var i = 0; i < this.length_; i++)
158 * Helper for selection previous or next.
159 * @param {boolean} offset If positive, select one forward (next).
160 * Else, select previous.
162 * @param {TimelineViewport} viewport The viewport to use to determine what
163 * is near to the current selection.
165 * @return {boolean} true if current selection changed.
167 getShiftedSelection: function(viewport, offset) {
168 var newSelection = new Selection();
169 for (var i = 0; i < this.length_; i++) {
172 var addEventToNewSelection = function(event) {
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);
182 } else if ((offset < 0) && event.previousFlowEvent) {
183 newSelection.push(event.previousFlowEvent);
188 var track = viewport.trackForEvent(event);
189 track.addItemNearToProvidedEventToSelection(
190 event, offset, newSelection);
193 if (newSelection.length == 0)