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 timeline viewport. 9 */ 10 base.require('event_target'); 11 base.exportTo('tracing', function() { 12 13 function TimelineSelectionSliceHit(track, slice) { 14 this.track = track; 15 this.slice = slice; 16 } 17 TimelineSelectionSliceHit.prototype = { 18 get selected() { 19 return this.slice.selected; 20 }, 21 set selected(v) { 22 this.slice.selected = v; 23 } 24 }; 25 26 function TimelineSelectionCounterSampleHit(track, counter, sampleIndex) { 27 this.track = track; 28 this.counter = counter; 29 this.sampleIndex = sampleIndex; 30 } 31 TimelineSelectionCounterSampleHit.prototype = { 32 get selected() { 33 return this.track.selectedSamples[this.sampleIndex] == true; 34 }, 35 set selected(v) { 36 if (v) 37 this.track.selectedSamples[this.sampleIndex] = true; 38 else 39 this.track.selectedSamples[this.sampleIndex] = false; 40 this.track.invalidate(); 41 } 42 }; 43 44 45 /** 46 * Represents a selection within a Timeline and its associated set of tracks. 47 * @constructor 48 */ 49 function TimelineSelection() { 50 this.range_dirty_ = true; 51 this.range_ = {}; 52 this.length_ = 0; 53 } 54 TimelineSelection.prototype = { 55 __proto__: Object.prototype, 56 57 get range() { 58 if (this.range_dirty_) { 59 var wmin = Infinity; 60 var wmax = -wmin; 61 for (var i = 0; i < this.length_; i++) { 62 var hit = this[i]; 63 if (hit.slice) { 64 wmin = Math.min(wmin, hit.slice.start); 65 wmax = Math.max(wmax, hit.slice.end); 66 } 67 } 68 this.range_ = { 69 min: wmin, 70 max: wmax 71 }; 72 this.range_dirty_ = false; 73 } 74 return this.range_; 75 }, 76 77 get duration() { 78 return this.range.max - this.range.min; 79 }, 80 81 get length() { 82 return this.length_; 83 }, 84 85 clear: function() { 86 for (var i = 0; i < this.length_; ++i) 87 delete this[i]; 88 this.length_ = 0; 89 this.range_dirty_ = true; 90 }, 91 92 push_: function(hit) { 93 this[this.length_++] = hit; 94 this.range_dirty_ = true; 95 return hit; 96 }, 97 98 addSlice: function(track, slice) { 99 return this.push_(new TimelineSelectionSliceHit(track, slice)); 100 }, 101 102 addCounterSample: function(track, counter, sampleIndex) { 103 return this.push_( 104 new TimelineSelectionCounterSampleHit( 105 track, counter, sampleIndex)); 106 }, 107 108 subSelection: function(index, count) { 109 count = count || 1; 110 111 var selection = new TimelineSelection(); 112 selection.range_dirty_ = true; 113 if (index < 0 || index + count > this.length_) 114 throw new Error('Index out of bounds'); 115 116 for (var i = index; i < index + count; i++) 117 selection.push_(this[i]); 118 119 return selection; 120 }, 121 122 getCounterSampleHits: function() { 123 var selection = new TimelineSelection(); 124 for (var i = 0; i < this.length_; i++) 125 if (this[i] instanceof TimelineSelectionCounterSampleHit) 126 selection.push_(this[i]); 127 return selection; 128 }, 129 130 getSliceHits: function() { 131 var selection = new TimelineSelection(); 132 for (var i = 0; i < this.length_; i++) 133 if (this[i] instanceof TimelineSelectionSliceHit) 134 selection.push_(this[i]); 135 return selection; 136 }, 137 138 map: function(fn) { 139 for (var i = 0; i < this.length_; i++) 140 fn(this[i]); 141 }, 142 143 /** 144 * Helper for selection previous or next. 145 * @param {boolean} forwardp If true, select one forward (next). 146 * Else, select previous. 147 * @return {boolean} true if current selection changed. 148 */ 149 getShiftedSelection: function(offset) { 150 var newSelection = new TimelineSelection(); 151 for (var i = 0; i < this.length_; i++) { 152 var hit = this[i]; 153 hit.track.addItemNearToProvidedHitToSelection( 154 hit, offset, newSelection); 155 } 156 157 if (newSelection.length == 0) 158 return undefined; 159 return newSelection; 160 } 161 }; 162 163 return { 164 TimelineSelectionSliceHit: TimelineSelectionSliceHit, 165 TimelineSelectionCounterSampleHit: TimelineSelectionCounterSampleHit, 166 TimelineSelection: TimelineSelection 167 }; 168 }); 169