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
7base.require('tracks.timeline_track');
8base.require('timeline_filter');
9base.require('ui');
10base.exportTo('tracks', function() {
11
12  /**
13   * A generic track that contains other tracks as its children.
14   * @constructor
15   */
16  var TimelineContainerTrack = base.ui.define(tracks.TimelineTrack);
17  TimelineContainerTrack.prototype = {
18    __proto__: tracks.TimelineTrack.prototype,
19
20    decorate: function() {
21      this.categoryFilter_ = new tracing.TimelineFilter();
22      this.headingWidth_ = undefined;
23      this.tracks_ = [];
24    },
25
26    detach: function() {
27      this.detachAllChildren();
28    },
29
30    detachAllChildren: function() {
31      for (var i = 0; i < this.tracks_.length; i++)
32        this.tracks_[i].detach();
33      this.tracks_ = [];
34      this.textContent = '';
35    },
36
37    get viewport() {
38      return this.viewport_;
39    },
40
41    set viewport(v) {
42      this.viewport_ = v;
43      for (var i = 0; i < this.tracks_.length; i++)
44        this.tracks_[i].viewport = v;
45    },
46
47    get firstCanvas() {
48      for (var i = 0; i < this.tracks_.length; i++)
49        if (this.tracks_[i].visible)
50          return this.tracks_[i].firstCanvas;
51      return undefined;
52    },
53
54    // The number of tracks actually displayed.
55    get numVisibleTracks() {
56      if (!this.visible)
57        return 0;
58      return this.numVisibleChildTracks;
59    },
60
61    // The number of tracks that would be displayed if this track were visible.
62    get numVisibleChildTracks() {
63      var sum = 0;
64      for (var i = 0; i < this.tracks_.length; ++i) {
65        sum += this.tracks_[i].numVisibleTracks;
66      }
67      return sum;
68    },
69
70    get headingWidth() {
71      return this.headingWidth_;
72    },
73
74    set headingWidth(w) {
75      this.headingWidth_ = w;
76      for (var i = 0; i < this.tracks_.length; ++i) {
77        this.tracks_[i].headingWidth = w;
78      }
79    },
80
81    get categoryFilter() {
82      return this.categoryFilter_;
83    },
84
85    set categoryFilter(v) {
86      this.categoryFilter_ = v;
87      for (var i = 0; i < this.tracks_.length; ++i) {
88        this.tracks_[i].categoryFilter = v;
89      }
90      this.applyCategoryFilter_();
91      this.updateFirstVisibleChildCSS();
92    },
93
94    applyCategoryFilter_: function() {
95    },
96
97    addTrack_: function(track) {
98      track.headingWidth = this.headingWidth_;
99      track.viewport = this.viewport_;
100      track.categoryFilter = this.categoryFilter;
101
102      this.tracks_.push(track);
103      this.appendChild(track);
104      return track;
105    },
106
107    updateFirstVisibleChildCSS: function() {
108      var isFirst = true;
109      for (var i = 0; i < this.tracks_.length; ++i) {
110        var track = this.tracks_[i];
111        if (isFirst && track.visible) {
112          track.classList.add('first-visible-child');
113          isFirst = false;
114        } else {
115          track.classList.remove('first-visible-child');
116        }
117      }
118    },
119
120    /**
121     * Adds items intersecting a point to a selection.
122     * @param {number} vX X location to search at, in viewspace.
123     * @param {number} vY Y location to search at, in viewspace.
124     * @param {TimelineSelection} selection Selection to which to add hits.
125     * @return {boolean} true if a slice was found, otherwise false.
126     */
127    addIntersectingItemsToSelection: function(vX, vY, selection) {
128      for (var i = 0; i < this.tracks_.length; i++) {
129        var trackClientRect = this.tracks_[i].getBoundingClientRect();
130        if (vY >= trackClientRect.top && vY < trackClientRect.bottom)
131          this.tracks_[i].addIntersectingItemsToSelection(vX, vY, selection);
132      }
133      return false;
134    },
135
136    /**
137     * Adds items intersecting the given range to a selection.
138     * @param {number} loVX Lower X bound of the interval to search, in
139     *     viewspace.
140     * @param {number} hiVX Upper X bound of the interval to search, in
141     *     viewspace.
142     * @param {number} loY Lower Y bound of the interval to search, in
143     *     viewspace space.
144     * @param {number} hiY Upper Y bound of the interval to search, in
145     *     viewspace space.
146     * @param {TimelineSelection} selection Selection to which to add hits.
147     */
148    addIntersectingItemsInRangeToSelection: function(
149        loVX, hiVX, loY, hiY, selection) {
150      for (var i = 0; i < this.tracks_.length; i++) {
151        var trackClientRect = this.tracks_[i].getBoundingClientRect();
152        var a = Math.max(loY, trackClientRect.top);
153        var b = Math.min(hiY, trackClientRect.bottom);
154        if (a <= b)
155          this.tracks_[i].addIntersectingItemsInRangeToSelection(
156              loVX, hiVX, loY, hiY, selection);
157      }
158    },
159
160    addAllObjectsMatchingFilterToSelection: function(filter, selection) {
161      for (var i = 0; i < this.tracks_.length; i++)
162        this.tracks_[i].addAllObjectsMatchingFilterToSelection(
163            filter, selection);
164    }
165  };
166
167  return {
168    TimelineContainerTrack: TimelineContainerTrack
169  };
170});
171