| <!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="/ui/tracks/rect_track.css"> |
| |
| <link rel="import" href="/base/sorted_array_utils.html"> |
| <link rel="import" href="/model/proxy_selectable_item.html"> |
| <link rel="import" href="/ui/base/draw_helpers.html"> |
| <link rel="import" href="/ui/base/fast_rect_renderer.html"> |
| <link rel="import" href="/ui/base/heading.html"> |
| <link rel="import" href="/ui/base/ui.html"> |
| <link rel="import" href="/ui/tracks/track.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('tr.ui.tracks', function() { |
| |
| /** |
| * A track that displays an array of Rect objects. |
| * @constructor |
| * @extends {Track} |
| */ |
| var RectTrack = tr.ui.b.define( |
| 'rect-track', tr.ui.tracks.Track); |
| |
| RectTrack.prototype = { |
| |
| __proto__: tr.ui.tracks.Track.prototype, |
| |
| decorate: function(viewport) { |
| tr.ui.tracks.Track.prototype.decorate.call(this, viewport); |
| this.classList.add('rect-track'); |
| this.asyncStyle_ = false; |
| this.rects_ = null; |
| |
| this.heading_ = document.createElement('tr-ui-heading'); |
| this.appendChild(this.heading_); |
| }, |
| |
| set heading(heading) { |
| this.heading_.heading = heading; |
| }, |
| |
| get heading() { |
| return this.heading_.heading; |
| }, |
| |
| set tooltip(tooltip) { |
| this.heading_.tooltip = tooltip; |
| }, |
| |
| set selectionGenerator(generator) { |
| this.heading_.selectionGenerator = generator; |
| }, |
| |
| set expanded(expanded) { |
| this.heading_.expanded = !!expanded; |
| }, |
| |
| set arrowVisible(arrowVisible) { |
| this.heading_.arrowVisible = !!arrowVisible; |
| }, |
| |
| get expanded() { |
| return this.heading_.expanded; |
| }, |
| |
| 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; |
| }, |
| |
| draw: function(type, viewLWorld, viewRWorld) { |
| switch (type) { |
| case tr.ui.tracks.DrawType.GENERAL_EVENT: |
| this.drawRects_(viewLWorld, viewRWorld); |
| break; |
| } |
| }, |
| |
| drawRects_: function(viewLWorld, viewRWorld) { |
| var ctx = this.context(); |
| |
| ctx.save(); |
| var bounds = this.getBoundingClientRect(); |
| tr.ui.b.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; |
| } |
| tr.ui.b.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) { |
| rect.addToTrackMap(eventToTrackMap, this); |
| }, this); |
| }, |
| |
| addIntersectingEventsInRangeToSelectionInWorldSpace: function( |
| loWX, hiWX, viewPixWidthWorld, selection) { |
| function onRect(rect) { |
| rect.addToSelection(selection); |
| } |
| onRect = onRect.bind(this); |
| tr.b.iterateOverIntersectingIntervals(this.rects_, |
| function(x) { return x.start; }, |
| function(x) { return x.duration; }, |
| loWX, hiWX, |
| onRect); |
| }, |
| |
| /** |
| * 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 |
| */ |
| addEventNearToProvidedEventToSelection: function(event, offset, selection) { |
| var index = tr.b.findFirstIndexInArray(this.rects_, function(rect) { |
| return rect.modelItem === event; |
| }); |
| if (index === -1) |
| return false; |
| |
| var newIndex = index + offset; |
| if (newIndex < 0 || newIndex >= this.rects_.length) |
| return false; |
| |
| this.rects_[newIndex].addToSelection(selection); |
| return true; |
| }, |
| |
| addAllEventsMatchingFilterToSelection: function(filter, selection) { |
| for (var i = 0; i < this.rects_.length; ++i) { |
| // TODO(petrcermak): Rather than unpacking the proxy item here, |
| // we should probably add an addToSelectionIfMatching(selection, filter) |
| // method to SelectableItem (#900). |
| var modelItem = this.rects_[i].modelItem; |
| if (!modelItem) |
| continue; |
| if (filter.matchSlice(modelItem)) |
| selection.push(modelItem); |
| } |
| }, |
| |
| addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY, |
| selection) { |
| var rect = tr.b.findClosestIntervalInSortedIntervals( |
| this.rects_, |
| function(x) { return x.start; }, |
| function(x) { return x.end; }, |
| worldX, |
| worldMaxDist); |
| |
| if (!rect) |
| return; |
| |
| rect.addToSelection(selection); |
| } |
| }; |
| |
| /** |
| * A filled rectangle with a title. |
| * |
| * @constructor |
| * @extends {ProxySelectableItem} |
| */ |
| function Rect(modelItem, title, colorId, start, duration) { |
| tr.model.ProxySelectableItem.call(this, modelItem); |
| this.title = title; |
| this.colorId = colorId; |
| this.start = start; |
| this.duration = duration; |
| this.end = start + duration; |
| }; |
| |
| Rect.prototype = { |
| __proto__: tr.model.ProxySelectableItem.prototype |
| }; |
| |
| return { |
| RectTrack: RectTrack, |
| Rect: Rect |
| }; |
| }); |
| </script> |