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() {
19 var RequestSelectionChangeEvent = tvcm.Event.bind(
20 undefined, 'requestSelectionChange', true, false);
24 constructor: tracing.trace_model.Slice,
29 constructor: tracing.trace_model.InstantEvent,
31 pluralName: 'instantEvents'
34 constructor: tracing.trace_model.CounterSample,
35 name: 'counterSample',
36 pluralName: 'counterSamples'
39 constructor: tracing.trace_model.ObjectSnapshot,
40 name: 'objectSnapshot',
41 pluralName: 'objectSnapshots'
44 constructor: tracing.trace_model.ObjectInstance,
45 name: 'objectInstance',
46 pluralName: 'objectInstances'
49 constructor: tracing.trace_model.Sample,
54 constructor: tracing.trace_model.FlowEvent,
56 pluralName: 'flowEvents'
61 * Represents a selection within a and its associated set of tracks.
64 function Selection(opt_events) {
65 this.bounds_dirty_ = true;
66 this.bounds_ = new tvcm.Range();
68 this.guid_ = tvcm.GUID.allocate();
71 for (var i = 0; i < opt_events.length; i++)
72 this.push(opt_events[i]);
75 Selection.prototype = {
76 __proto__: Object.prototype,
79 if (this.bounds_dirty_) {
81 for (var i = 0; i < this.length_; i++)
82 this[i].addBoundsToRange(this.bounds_);
83 this.bounds_dirty_ = false;
89 if (this.bounds_.isEmpty)
91 return this.bounds_.max - this.bounds_.min;
103 for (var i = 0; i < this.length_; ++i)
106 this.bounds_dirty_ = true;
109 push: function(event) {
110 this[this.length_++] = event;
111 this.bounds_dirty_ = true;
115 addSelection: function(selection) {
116 for (var i = 0; i < selection.length; i++)
117 this.push(selection[i]);
120 subSelection: function(index, count) {
123 var selection = new Selection();
124 selection.bounds_dirty_ = true;
125 if (index < 0 || index + count > this.length_)
126 throw new Error('Index out of bounds');
128 for (var i = index; i < index + count; i++)
129 selection.push(this[i]);
134 getEventsOrganizedByType: function() {
136 EVENT_TYPES.forEach(function(eventType) {
137 events[eventType.pluralName] = new Selection();
139 for (var i = 0; i < this.length_; i++) {
141 EVENT_TYPES.forEach(function(eventType) {
142 if (event instanceof eventType.constructor)
143 events[eventType.pluralName].push(event);
149 enumEventsOfType: function(type, func) {
150 for (var i = 0; i < this.length_; i++)
151 if (this[i] instanceof type)
156 for (var i = 0; i < this.length_; i++)
161 * Helper for selection previous or next.
162 * @param {boolean} offset If positive, select one forward (next).
163 * Else, select previous.
165 * @param {TimelineViewport} viewport The viewport to use to determine what
166 * is near to the current selection.
168 * @return {boolean} true if current selection changed.
170 getShiftedSelection: function(viewport, offset) {
171 var newSelection = new Selection();
172 for (var i = 0; i < this.length_; i++) {
175 var addEventToNewSelection = function(event) {
178 // If this is a flow event, and we have a next/prev item in the chain
179 // then we use that as the item to move too. Otherwise, we let the
180 // normal movement for a slice kick in and use that.
181 if (event instanceof tracing.trace_model.FlowEvent) {
182 if ((offset > 0) && event.nextFlowEvent) {
183 newSelection.push(event.nextFlowEvent);
185 } else if ((offset < 0) && event.previousFlowEvent) {
186 newSelection.push(event.previousFlowEvent);
191 var track = viewport.trackForEvent(event);
192 track.addItemNearToProvidedEventToSelection(
193 event, offset, newSelection);
196 if (newSelection.length == 0)
203 Selection: Selection,
204 RequestSelectionChangeEvent: RequestSelectionChangeEvent