blob: f390182bbb56a3243dbe0eb88b59be79631eec04 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 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.
-->
<link rel="stylesheet" href="/core/tracks/rect_track.css">
<link rel="import" href="/core/tracks/heading_track.html">
<link rel="import" href="/core/fast_rect_renderer.html">
<link rel="import" href="/core/draw_helpers.html">
<link rel="import" href="/base/sorted_array_utils.html">
<link rel="import" href="/base/ui.html">
<script>
'use strict';
tv.exportTo('tv.c.tracks', function() {
/**
* A track that displays an array of Rect objects.
* @constructor
* @extends {HeadingTrack}
*/
var RectTrack = tv.b.ui.define(
'rect-track', tv.c.tracks.HeadingTrack);
RectTrack.prototype = {
__proto__: tv.c.tracks.HeadingTrack.prototype,
decorate: function(viewport) {
tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
this.classList.add('rect-track');
this.asyncStyle_ = false;
this.rects_ = null;
},
get asyncStyle() {
return this.asyncStyle_;
},
set asyncStyle(v) {
this.asyncStyle_ = !!v;
},
get rects() {
return this.rects_;
},
set rects(rects) {
this.rects_ = rects || [];
this.invalidateDrawingContainer();
},
get height() {
return window.getComputedStyle(this).height;
},
set height(height) {
this.style.height = height;
this.invalidateDrawingContainer();
},
get hasVisibleContent() {
return this.rects_.length > 0;
},
getModelEventFromItem: function(rect) {
throw new Error('Not implemented.');
},
draw: function(type, viewLWorld, viewRWorld) {
switch (type) {
case tv.c.tracks.DrawType.SLICE:
this.drawRects_(viewLWorld, viewRWorld);
break;
}
},
drawRects_: function(viewLWorld, viewRWorld) {
var ctx = this.context();
ctx.save();
var bounds = this.getBoundingClientRect();
tv.c.drawSlices(
ctx,
this.viewport.currentDisplayTransform,
viewLWorld,
viewRWorld,
bounds.height,
this.rects_,
this.asyncStyle_);
ctx.restore();
if (bounds.height <= 6)
return;
var fontSize, yOffset;
if (bounds.height < 15) {
fontSize = 6;
yOffset = 1.0;
} else {
fontSize = 10;
yOffset = 2.5;
}
tv.c.drawLabels(
ctx,
this.viewport.currentDisplayTransform,
viewLWorld,
viewRWorld,
this.rects_,
this.asyncStyle_,
fontSize,
yOffset);
},
addEventsToTrackMap: function(eventToTrackMap) {
if (this.rects_ === undefined || this.rects_ === null)
return;
this.rects_.forEach(function(rect) {
var event = this.getModelEventFromItem(rect);
if (event)
eventToTrackMap.addEvent(event, this);
}, this);
},
addIntersectingItemsInRangeToSelectionInWorldSpace: function(
loWX, hiWX, viewPixWidthWorld, selection) {
function onRect(rect) {
var event = this.getModelEventFromItem(rect);
if (event)
selection.push(event);
}
onRect = onRect.bind(this);
tv.b.iterateOverIntersectingIntervals(this.rects_,
function(x) { return x.start; },
function(x) { return x.duration; },
loWX, hiWX,
onRect);
},
/**
* Find the index for the given rect.
* @return {index} Index of the given rect, or undefined.
* @private
*/
indexOfRect_: function(rect) {
var index = tv.b.findLowIndexInSortedArray(this.rects_,
function(x) { return x.start; },
rect.start);
while (index < this.rects_.length &&
rect.start == this.rects_[index].start &&
rect.colorId != this.rects_[index].colorId) {
index++;
}
return index < this.rects_.length ? index : undefined;
},
/**
* Add the item to the left or right of the provided event, if any, to the
* selection.
* @param {rect} The current rect.
* @param {Number} offset Number of rects away from the event to look.
* @param {Selection} selection The selection to add an event to,
* if found.
* @return {boolean} Whether an event was found.
* @private
*/
addItemNearToProvidedEventToSelection: function(event, offset, selection) {
var index = this.indexOfRect_(event);
if (index === undefined)
return false;
var newIndex = index + offset;
if (newIndex < 0 || newIndex >= this.rects_.length)
return false;
var event = this.rects_[newIndex];
if (event)
selection.push(event);
return true;
},
addAllObjectsMatchingFilterToSelection: function(filter, selection) {
for (var i = 0; i < this.rects_.length; ++i) {
if (filter.matchSlice(this.rects_[i])) {
var event = this.getModelEventFromItem(this.rects_[i]);
if (event)
selection.push(event);
}
}
},
addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
selection) {
var rect = tv.b.findClosestIntervalInSortedIntervals(
this.rects_,
function(x) { return x.start; },
function(x) { return x.end; },
worldX,
worldMaxDist);
if (rect) {
var event = this.getModelEventFromItem(rect);
if (event)
selection.push(event);
}
}
};
return {
RectTrack: RectTrack
};
});
</script>