blob: d99c62bacacf3eef2cb50c059197d3800c521da4 [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WI.RecordingTabContentView = class RecordingTabContentView extends WI.ContentBrowserTabContentView
{
constructor()
{
let {image, title} = WI.RecordingTabContentView.tabInfo();
let tabBarItem = new WI.GeneralTabBarItem(image, title);
const navigationSidebarPanelConstructor = WI.RecordingNavigationSidebarPanel;
const detailsSidebarPanelConstructors = [WI.RecordingStateDetailsSidebarPanel, WI.RecordingTraceDetailsSidebarPanel, WI.CanvasDetailsSidebarPanel];
const disableBackForward = true;
let flexibleNavigationItem = new WI.ScrubberNavigationItem;
super("recording", "recording", tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward, flexibleNavigationItem);
this._visualActionIndexes = [];
this._scrubberNavigationItem = flexibleNavigationItem;
this._scrubberNavigationItem.value = 0;
this._scrubberNavigationItem.disabled = true;
this._scrubberNavigationItem.addEventListener(WI.ScrubberNavigationItem.Event.ValueChanged, this._scrubberNavigationItemValueChanged, this);
this.navigationSidebarPanel.addEventListener(WI.RecordingNavigationSidebarPanel.Event.Import, this._navigationSidebarImport, this);
this.navigationSidebarPanel.contentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._navigationSidebarTreeOutlineSelectionChanged, this);
this._recording = null;
}
// Static
static tabInfo()
{
return {
image: "Images/Recording.svg",
title: WI.UIString("Recording"),
};
}
static isTabAllowed()
{
return !!window.CanvasAgent;
}
// Public
get type()
{
return WI.RecordingTabContentView.Type;
}
canShowRepresentedObject(representedObject)
{
// Once a recording has been loaded for this tab, do not allow another one to be loaded.
// This will cause new tabs to be opened for each recording, which is the desired behavior.
if (this._recording)
return false;
return representedObject instanceof WI.Recording;
}
showRepresentedObject(representedObject, cookie)
{
super.showRepresentedObject(representedObject, cookie);
this._recording = representedObject;
this._recording.actions.then((actions) => {
this._visualActionIndexes = [];
actions.forEach((action, i) => {
if (action.isVisual)
this._visualActionIndexes.push(i);
});
this._scrubberNavigationItem.value = 0;
this._scrubberNavigationItem.min = 0;
this._scrubberNavigationItem.max = actions.length - 1;
this._scrubberNavigationItem.disabled = false;
this.navigationSidebarPanel.recording = this._recording;
this._updateActionIndex(this._scrubberNavigationItem.value);
});
}
// Protected
restoreStateFromCookie(restorationType)
{
// Don't attempt to do anything to this tab.
}
saveStateToCookie(cookie)
{
// Don't attempt to do anything to this tab.
}
closed()
{
super.closed();
for (let detailsSidebarPanel of this.detailsSidebarPanels)
detailsSidebarPanel.recording = null;
this.navigationSidebarPanel.recording = null;
}
// Private
_updateActionIndex(index, options = {})
{
this._scrubberNavigationItem.value = index;
options.actionCompletedCallback = (action, context) => {
for (let detailsSidebarPanel of this.detailsSidebarPanels) {
if (detailsSidebarPanel.updateAction)
detailsSidebarPanel.updateAction(action, context, options);
}
};
this.contentBrowser.currentContentView.updateActionIndex(index, options);
// This must be placed last, as it is possible for the update of the NavigationSidebarPanel
// to trigger another update of the index, such as if the selected index is not expanded.
if (!options.suppressNavigationUpdate)
this.navigationSidebarPanel.updateActionIndex(index, options);
}
_scrubberNavigationItemValueChanged(event)
{
for (let i = 0; i <= this._visualActionIndexes.length; ++i) {
if (this._visualActionIndexes[i] < this._scrubberNavigationItem.value)
continue;
let min = i ? this._visualActionIndexes[i - 1] : this._scrubberNavigationItem.min;
let max = i < this._visualActionIndexes.length ? this._visualActionIndexes[i] : this._scrubberNavigationItem.max;
this._updateActionIndex(this._scrubberNavigationItem.value >= (min + max) / 2 ? max : min);
return;
}
}
_navigationSidebarImport(event)
{
let recording = WI.Recording.fromPayload(event.data.payload);
if (!recording) {
WI.Recording.synthesizeError(WI.UIString("unsupported version."));
return;
}
this.showRepresentedObject(recording);
}
_navigationSidebarTreeOutlineSelectionChanged(event)
{
// Ignore deselect events.
if (!event.data.selectedElement)
return;
let options = {suppressNavigationUpdate: true};
let selectedTreeElement = this.navigationSidebarPanel.contentTreeOutline.selectedTreeElement;
if (selectedTreeElement instanceof WI.FolderTreeElement)
selectedTreeElement = selectedTreeElement.children.lastValue;
this._updateActionIndex(selectedTreeElement.index, options);
}
};
WI.RecordingTabContentView.Type = "recording";