blob: f390182bbb56a3243dbe0eb88b59be79631eec04 [file] [log] [blame]
Chris Craikb122baf2015-03-05 13:58:42 -08001<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="stylesheet" href="/core/tracks/rect_track.css">
9
10<link rel="import" href="/core/tracks/heading_track.html">
11<link rel="import" href="/core/fast_rect_renderer.html">
12<link rel="import" href="/core/draw_helpers.html">
13<link rel="import" href="/base/sorted_array_utils.html">
14<link rel="import" href="/base/ui.html">
15
16<script>
17'use strict';
18
19tv.exportTo('tv.c.tracks', function() {
20
21 /**
22 * A track that displays an array of Rect objects.
23 * @constructor
24 * @extends {HeadingTrack}
25 */
26 var RectTrack = tv.b.ui.define(
27 'rect-track', tv.c.tracks.HeadingTrack);
28
29 RectTrack.prototype = {
30
31 __proto__: tv.c.tracks.HeadingTrack.prototype,
32
33 decorate: function(viewport) {
34 tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
35 this.classList.add('rect-track');
36 this.asyncStyle_ = false;
37 this.rects_ = null;
38 },
39
40 get asyncStyle() {
41 return this.asyncStyle_;
42 },
43
44 set asyncStyle(v) {
45 this.asyncStyle_ = !!v;
46 },
47
48 get rects() {
49 return this.rects_;
50 },
51
52 set rects(rects) {
53 this.rects_ = rects || [];
54 this.invalidateDrawingContainer();
55 },
56
57 get height() {
58 return window.getComputedStyle(this).height;
59 },
60
61 set height(height) {
62 this.style.height = height;
63 this.invalidateDrawingContainer();
64 },
65
66 get hasVisibleContent() {
67 return this.rects_.length > 0;
68 },
69
70 getModelEventFromItem: function(rect) {
71 throw new Error('Not implemented.');
72 },
73
74 draw: function(type, viewLWorld, viewRWorld) {
75 switch (type) {
76 case tv.c.tracks.DrawType.SLICE:
77 this.drawRects_(viewLWorld, viewRWorld);
78 break;
79 }
80 },
81
82 drawRects_: function(viewLWorld, viewRWorld) {
83 var ctx = this.context();
84
85 ctx.save();
86 var bounds = this.getBoundingClientRect();
87 tv.c.drawSlices(
88 ctx,
89 this.viewport.currentDisplayTransform,
90 viewLWorld,
91 viewRWorld,
92 bounds.height,
93 this.rects_,
94 this.asyncStyle_);
95 ctx.restore();
96
97 if (bounds.height <= 6)
98 return;
99
100 var fontSize, yOffset;
101 if (bounds.height < 15) {
102 fontSize = 6;
103 yOffset = 1.0;
104 } else {
105 fontSize = 10;
106 yOffset = 2.5;
107 }
108 tv.c.drawLabels(
109 ctx,
110 this.viewport.currentDisplayTransform,
111 viewLWorld,
112 viewRWorld,
113 this.rects_,
114 this.asyncStyle_,
115 fontSize,
116 yOffset);
117 },
118
119 addEventsToTrackMap: function(eventToTrackMap) {
120 if (this.rects_ === undefined || this.rects_ === null)
121 return;
122
123 this.rects_.forEach(function(rect) {
124 var event = this.getModelEventFromItem(rect);
125 if (event)
126 eventToTrackMap.addEvent(event, this);
127 }, this);
128 },
129
130 addIntersectingItemsInRangeToSelectionInWorldSpace: function(
131 loWX, hiWX, viewPixWidthWorld, selection) {
132 function onRect(rect) {
133 var event = this.getModelEventFromItem(rect);
134 if (event)
135 selection.push(event);
136 }
137 onRect = onRect.bind(this);
138 tv.b.iterateOverIntersectingIntervals(this.rects_,
139 function(x) { return x.start; },
140 function(x) { return x.duration; },
141 loWX, hiWX,
142 onRect);
143 },
144
145 /**
146 * Find the index for the given rect.
147 * @return {index} Index of the given rect, or undefined.
148 * @private
149 */
150 indexOfRect_: function(rect) {
151 var index = tv.b.findLowIndexInSortedArray(this.rects_,
152 function(x) { return x.start; },
153 rect.start);
154 while (index < this.rects_.length &&
155 rect.start == this.rects_[index].start &&
156 rect.colorId != this.rects_[index].colorId) {
157 index++;
158 }
159 return index < this.rects_.length ? index : undefined;
160 },
161
162 /**
163 * Add the item to the left or right of the provided event, if any, to the
164 * selection.
165 * @param {rect} The current rect.
166 * @param {Number} offset Number of rects away from the event to look.
167 * @param {Selection} selection The selection to add an event to,
168 * if found.
169 * @return {boolean} Whether an event was found.
170 * @private
171 */
172 addItemNearToProvidedEventToSelection: function(event, offset, selection) {
173 var index = this.indexOfRect_(event);
174 if (index === undefined)
175 return false;
176
177 var newIndex = index + offset;
178 if (newIndex < 0 || newIndex >= this.rects_.length)
179 return false;
180
181 var event = this.rects_[newIndex];
182 if (event)
183 selection.push(event);
184 return true;
185 },
186
187 addAllObjectsMatchingFilterToSelection: function(filter, selection) {
188 for (var i = 0; i < this.rects_.length; ++i) {
189 if (filter.matchSlice(this.rects_[i])) {
190 var event = this.getModelEventFromItem(this.rects_[i]);
191 if (event)
192 selection.push(event);
193 }
194 }
195 },
196
197 addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
198 selection) {
199 var rect = tv.b.findClosestIntervalInSortedIntervals(
200 this.rects_,
201 function(x) { return x.start; },
202 function(x) { return x.end; },
203 worldX,
204 worldMaxDist);
205
206 if (rect) {
207 var event = this.getModelEventFromItem(rect);
208 if (event)
209 selection.push(event);
210 }
211 }
212 };
213
214 return {
215 RectTrack: RectTrack
216 };
217});
218</script>