Javascript  |  187行  |  4.58 KB

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @fileoverview Code for the viewport.
 */
base.require('range');
base.require('event_target');
base.exportTo('tracing', function() {

  function SelectionSliceHit(track, slice) {
    this.track = track;
    this.slice = slice;
  }
  SelectionSliceHit.prototype = {
    get selected() {
      return this.slice.selected;
    },
    set selected(v) {
      this.slice.selected = v;
    }
  };

  function SelectionCounterSampleHit(track, counter, sampleIndex) {
    this.track = track;
    this.counter = counter;
    this.sampleIndex = sampleIndex;
  }
  SelectionCounterSampleHit.prototype = {
    get selected() {
      return this.track.selectedSamples[this.sampleIndex] == true;
    },
    set selected(v) {
      if (v)
        this.track.selectedSamples[this.sampleIndex] = true;
      else
        this.track.selectedSamples[this.sampleIndex] = false;
      this.track.invalidate();
    }
  };


  /**
   * Represents a selection within a  and its associated set of tracks.
   * @constructor
   */
  function Selection() {
    this.bounds_dirty_ = true;
    this.bounds_ = new base.Range();
    this.length_ = 0;
  }
  Selection.prototype = {
    __proto__: Object.prototype,

    get bounds() {
      if (this.bounds_dirty_) {
        this.bounds_.reset();
        for (var i = 0; i < this.length_; i++) {
          var hit = this[i];
          if (hit.slice) {
            this.bounds_.addValue(hit.slice.start);
            this.bounds_.addValue(hit.slice.end);
          }
        }
        this.bounds_dirty_ = false;
      }
      return this.bounds_;
    },

    get duration() {
      if (this.bounds_.isEmpty)
        return 0;
      return this.bounds_.max - this.bounds_.min;
    },

    get length() {
      return this.length_;
    },

    clear: function() {
      for (var i = 0; i < this.length_; ++i)
        delete this[i];
      this.length_ = 0;
      this.bounds_dirty_ = true;
    },

    pushHit: function(hit) {
      this.push_(hit);
    },

    push_: function(hit) {
      this[this.length_++] = hit;
      this.bounds_dirty_ = true;
      return hit;
    },

    addSlice: function(track, slice) {
      return this.push_(new SelectionSliceHit(track, slice));
    },

    addCounterSample: function(track, counter, sampleIndex) {
      return this.push_(
          new SelectionCounterSampleHit(
          track, counter, sampleIndex));
    },

    subSelection: function(index, count) {
      count = count || 1;

      var selection = new Selection();
      selection.bounds_dirty_ = true;
      if (index < 0 || index + count > this.length_)
        throw new Error('Index out of bounds');

      for (var i = index; i < index + count; i++)
        selection.push_(this[i]);

      return selection;
    },

    getCounterSampleHitsAsSelection: function() {
      var selection = new Selection();
      for (var i = 0; i < this.length_; i++)
        if (this[i] instanceof SelectionCounterSampleHit)
          selection.push_(this[i]);
      return selection;
    },

    getSliceHitsAsSelection: function() {
      var selection = new Selection();
      for (var i = 0; i < this.length_; i++)
        if (this[i] instanceof SelectionSliceHit)
          selection.push_(this[i]);
      return selection;
    },

    getNumSliceHits: function() {
      var numHits = 0;
      for (var i = 0; i < this.length_; i++)
        if (this[i] instanceof SelectionSliceHit)
          numHits++;
      return numHits;
    },

    getNumCounterHits: function() {
      var numHits = 0;
      for (var i = 0; i < this.length_; i++)
        if (this[i] instanceof SelectionCounterSampleHit)
          numHits++;
      return numHits;
    },

    map: function(fn) {
      for (var i = 0; i < this.length_; i++)
        fn(this[i]);
    },

    /**
     * Helper for selection previous or next.
     * @param {boolean} forwardp If true, select one forward (next).
     *   Else, select previous.
     * @return {boolean} true if current selection changed.
     */
    getShiftedSelection: function(offset) {
      var newSelection = new Selection();
      for (var i = 0; i < this.length_; i++) {
        var hit = this[i];
        hit.track.addItemNearToProvidedHitToSelection(
            hit, offset, newSelection);
      }

      if (newSelection.length == 0)
        return undefined;
      return newSelection;
    }
  };

  return {
    SelectionSliceHit: SelectionSliceHit,
    SelectionCounterSampleHit: SelectionCounterSampleHit,
    Selection: Selection
  };
});