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