| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2015 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="import" href="/tracing/base/base.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('tr.model', function() { |
| /** |
| * YComponent is a class that handles storing the stableId and the percentage |
| * offset in the y direction of all tracks within a specific viewX and viewY |
| * coordinate. |
| * @constructor |
| */ |
| function YComponent(stableId, yPercentOffset) { |
| this.stableId = stableId; |
| this.yPercentOffset = yPercentOffset; |
| } |
| |
| YComponent.prototype = { |
| toDict: function() { |
| return { |
| stableId: this.stableId, |
| yPercentOffset: this.yPercentOffset |
| }; |
| } |
| }; |
| |
| /** |
| * Location is a class that represents a spatial location on the timeline |
| * that is specified by percent offsets within tracks rather than specific |
| * points. |
| * |
| * @constructor |
| */ |
| function Location(xWorld, yComponents) { |
| this.xWorld_ = xWorld; |
| this.yComponents_ = yComponents; |
| }; |
| |
| /** |
| * Returns a new Location given by x and y coordinates with respect to |
| * the timeline's drawing canvas. |
| */ |
| Location.fromViewCoordinates = function(viewport, viewX, viewY) { |
| var dt = viewport.currentDisplayTransform; |
| var xWorld = dt.xViewToWorld(viewX); |
| var yComponents = []; |
| |
| // Since we're given coordinates within the timeline canvas, we need to |
| // convert them to document coordinates to get the element. |
| var elem = document.elementFromPoint( |
| viewX + viewport.modelTrackContainer.canvas.offsetLeft, |
| viewY + viewport.modelTrackContainer.canvas.offsetTop); |
| // Build yComponents by calculating percentage offset with respect to |
| // each parent track. |
| while (elem instanceof tr.ui.tracks.Track) { |
| if (elem.eventContainer) { |
| var boundRect = elem.getBoundingClientRect(); |
| var yPercentOffset = (viewY - boundRect.top) / boundRect.height; |
| yComponents.push( |
| new YComponent(elem.eventContainer.stableId, yPercentOffset)); |
| } |
| elem = elem.parentElement; |
| } |
| |
| if (yComponents.length == 0) |
| return; |
| return new Location(xWorld, yComponents); |
| } |
| |
| Location.fromStableIdAndTimestamp = function(viewport, stableId, ts) { |
| var xWorld = ts; |
| var yComponents = []; |
| |
| // The y components' percentage offsets will be calculated with respect to |
| // the boundingRect's top of containing track. |
| var containerToTrack = viewport.containerToTrackMap; |
| var elem = containerToTrack.getTrackByStableId(stableId); |
| if (!elem) |
| return; |
| |
| var firstY = elem.getBoundingClientRect().top; |
| while (elem instanceof tr.ui.tracks.Track) { |
| if (elem.eventContainer) { |
| var boundRect = elem.getBoundingClientRect(); |
| var yPercentOffset = (firstY - boundRect.top) / boundRect.height; |
| yComponents.push( |
| new YComponent(elem.eventContainer.stableId, yPercentOffset)); |
| } |
| elem = elem.parentElement; |
| } |
| |
| if (yComponents.length == 0) |
| return; |
| return new Location(xWorld, yComponents); |
| } |
| |
| Location.prototype = { |
| |
| get xWorld() { |
| return this.xWorld_; |
| }, |
| |
| /** |
| * Returns the first valid containing track based on the |
| * internal yComponents. |
| */ |
| getContainingTrack: function(viewport) { |
| var containerToTrack = viewport.containerToTrackMap; |
| for (var i in this.yComponents_) { |
| var yComponent = this.yComponents_[i]; |
| var track = containerToTrack.getTrackByStableId(yComponent.stableId); |
| if (track !== undefined) |
| return track; |
| } |
| }, |
| |
| /** |
| * Calculates and returns x and y coordinates of the current location with |
| * respect to the timeline's canvas. |
| */ |
| toViewCoordinates: function(viewport) { |
| var dt = viewport.currentDisplayTransform; |
| var containerToTrack = viewport.containerToTrackMap; |
| var viewX = dt.xWorldToView(this.xWorld_); |
| |
| var viewY = -1; |
| for (var index in this.yComponents_) { |
| var yComponent = this.yComponents_[index]; |
| var track = containerToTrack.getTrackByStableId(yComponent.stableId); |
| if (track !== undefined) { |
| var boundRect = track.getBoundingClientRect(); |
| viewY = yComponent.yPercentOffset * boundRect.height + boundRect.top; |
| break; |
| } |
| } |
| |
| return { |
| viewX: viewX, |
| viewY: viewY |
| }; |
| }, |
| |
| toDict: function() { |
| return { |
| xWorld: this.xWorld_, |
| yComponents: this.yComponents_ |
| }; |
| } |
| }; |
| |
| return { |
| Location: Location |
| }; |
| }); |
| </script> |