blob: d30741adf187c09d1574abd51fb8ea54bc679fef [file] [log] [blame]
<!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="/core/analysis/analysis_link.html">
<link rel="import" href="/core/analysis/flow_classifier.html">
<link rel="import" href="/core/selection.html">
<link rel="import" href="/base/ui/table.html">
<link rel="import" href="/base/ui/dom_helpers.html">
<polymer-element name="tr-c-a-related-events">
<template>
<style>
:host {
display: flex;
flex-direction: column;
}
#table {
flex: 1 1 auto;
align-self: stretch;
}
</style>
<tr-b-ui-table id="table"></tr-b-ui-table>
</template>
<script>
'use strict';
Polymer({
ready: function() {
this.eventGroups_ = [];
this.$.table.tableColumns = [
{
title: 'Event(s)',
value: function(row) { return row.type; },
width: '150px'
},
{
title: 'Link',
width: '100%',
value: function(row) {
var linkEl = document.createElement('tr-c-a-analysis-link');
if (row.name)
linkEl.setSelectionAndContent(row.selection, row.name);
else
linkEl.selection = row.selection;
return linkEl;
}
}
];
},
hasRelatedEvents: function() {
return (this.eventGroups_ && this.eventGroups_.length > 0);
},
addRelatedEvents: function(selection) {
this.addConnectedFlows_(selection);
this.addConnectedEvents_(selection);
this.updateContents_();
},
addConnectedFlows_: function(selection) {
var classifier = new tr.c.analysis.FlowClassifier();
selection.forEach(function(slice) {
if (slice.inFlowEvents) {
slice.inFlowEvents.forEach(function(flow) {
classifier.addInFlow(flow);
});
}
if (slice.outFlowEvents) {
slice.outFlowEvents.forEach(function(flow) {
classifier.addOutFlow(flow);
});
}
});
if (!classifier.hasEvents())
return;
var addToEventGroups = function(type, flowEvent) {
this.eventGroups_.push({
type: type,
selection: new tr.c.Selection(flowEvent),
name: flowEvent.title
});
};
classifier.inFlowEvents.forEach(
addToEventGroups.bind(this, 'Incoming flow'));
classifier.outFlowEvents.forEach(
addToEventGroups.bind(this, 'Outgoing flow'));
classifier.internalFlowEvents.forEach(
addToEventGroups.bind(this, 'Internal flow'));
},
addConnectedEvents_: function(selection) {
// Preceding and following events are only well-defined for single
// selections.
if (selection.length === 1)
this.addConnectedEventsForSlice_(selection[0]);
else
this.addConnectedEventsForSelection_(selection);
},
addConnectedEventsForSlice_: function(slice) {
var precedingEventsSelection = undefined;
var followingEventsSelection = undefined;
if (slice.inFlowEvents && slice.inFlowEvents.length !== 0) {
precedingEventsSelection = new tr.c.Selection();
this.recursivelyAddConnectedEvents_(precedingEventsSelection, {}, slice,
function(event) { return event.inFlowEvents; });
this.eventGroups_.push({
type: 'Preceding events',
selection: precedingEventsSelection
});
}
if (slice.outFlowEvents && slice.outFlowEvents.length !== 0) {
followingEventsSelection = new tr.c.Selection();
this.recursivelyAddConnectedEvents_(followingEventsSelection, {}, slice,
function(event) { return event.outFlowEvents; });
this.eventGroups_.push({
type: 'Following events',
selection: followingEventsSelection
});
}
if (precedingEventsSelection && followingEventsSelection) {
var allEventsSelection = new tr.c.Selection();
for (var i = 0; i < precedingEventsSelection.length; ++i)
allEventsSelection.push(precedingEventsSelection[i]);
// Do not add the first event of followingEventsSelection since it's
// the slice too.
for (var i = 1; i < followingEventsSelection.length; ++i)
allEventsSelection.push(followingEventsSelection[i]);
this.eventGroups_.push({
type: 'All connected events',
selection: allEventsSelection
});
}
},
addConnectedEventsForSelection_: function(selection) {
var eventIds = {};
var allEventsSelection = new tr.c.Selection();
selection.forEach(function(slice) {
this.recursivelyAddConnectedEvents_(allEventsSelection, eventIds, slice,
function(event) {
var flows = [];
if (event.inFlowEvents)
flows = flows.concat(event.inFlowEvents);
if (event.outFlowEvents)
flows = flows.concat(event.outFlowEvents);
return flows;
});
}.bind(this));
// Add related events if it contains more than the original selection.
if (allEventsSelection.length > selection.length) {
this.eventGroups_.push({
type: 'All connected events',
selection: allEventsSelection
});
}
},
updateContents_: function() {
var table = this.$.table;
if (this.eventGroups_ === undefined)
table.tableRows = [];
else
table.tableRows = this.eventGroups_.slice();
table.rebuild();
},
recursivelyAddConnectedEvents_: function(selection, eventIds, event,
getFlows) {
if (!event || eventIds[event.guid])
return;
eventIds[event.guid] = true;
selection.push(event);
var flowEvents = getFlows(event);
if (!flowEvents)
return;
for (var i = 0; i < flowEvents.length; ++i) {
selection.push(flowEvents[i]);
this.recursivelyAddConnectedEvents_(selection, eventIds,
flowEvents[i].startSlice, getFlows);
this.recursivelyAddConnectedEvents_(selection, eventIds,
flowEvents[i].endSlice, getFlows);
}
}
});
</script>
</polymer-element>