2020-07-14 15:03:14 +00:00
|
|
|
// Copyright 2020 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2020-11-03 08:01:33 +00:00
|
|
|
import {SourcePosition} from '../profile.mjs';
|
2020-09-28 13:50:56 +00:00
|
|
|
|
2020-11-03 08:01:33 +00:00
|
|
|
import {State} from './app-model.mjs';
|
2020-12-03 17:48:45 +00:00
|
|
|
import {ApiLogEntry} from './log/api.mjs';
|
|
|
|
import {DeoptLogEntry} from './log/code.mjs';
|
2020-12-01 19:37:17 +00:00
|
|
|
import {CodeLogEntry} from './log/code.mjs';
|
2020-11-03 08:01:33 +00:00
|
|
|
import {IcLogEntry} from './log/ic.mjs';
|
|
|
|
import {MapLogEntry} from './log/map.mjs';
|
|
|
|
import {Processor} from './processor.mjs';
|
2020-11-26 14:07:19 +00:00
|
|
|
import {FocusEvent, SelectionEvent, SelectTimeEvent, ToolTipEvent,} from './view/events.mjs';
|
2020-12-07 08:44:54 +00:00
|
|
|
import {$, CSSColor, groupBy} from './view/helper.mjs';
|
2020-09-28 13:50:56 +00:00
|
|
|
|
2020-07-16 10:02:52 +00:00
|
|
|
class App {
|
2020-10-19 10:45:42 +00:00
|
|
|
_state;
|
|
|
|
_view;
|
|
|
|
_navigation;
|
2020-10-23 11:21:18 +00:00
|
|
|
_startupPromise;
|
2020-12-03 17:48:45 +00:00
|
|
|
constructor() {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view = {
|
2020-10-19 16:48:36 +00:00
|
|
|
__proto__: null,
|
2020-12-03 17:48:45 +00:00
|
|
|
logFileReader: $('#log-file-reader'),
|
2020-12-07 08:44:54 +00:00
|
|
|
|
2020-12-03 17:48:45 +00:00
|
|
|
timelinePanel: $('#timeline-panel'),
|
|
|
|
mapTrack: $('#map-track'),
|
|
|
|
icTrack: $('#ic-track'),
|
|
|
|
deoptTrack: $('#deopt-track'),
|
|
|
|
codeTrack: $('#code-track'),
|
|
|
|
apiTrack: $('#api-track'),
|
2020-12-07 08:44:54 +00:00
|
|
|
|
|
|
|
icList: $('#ic-list'),
|
|
|
|
mapList: $('#map-list'),
|
|
|
|
codeList: $('#code-list'),
|
|
|
|
deoptList: $('#deopt-list'),
|
|
|
|
apiList: $('#api-list'),
|
|
|
|
|
|
|
|
mapPanel: $('#map-panel'),
|
|
|
|
codePanel: $('#code-panel'),
|
2020-12-03 17:48:45 +00:00
|
|
|
sourcePanel: $('#source-panel'),
|
2020-12-07 08:44:54 +00:00
|
|
|
|
2020-12-03 17:48:45 +00:00
|
|
|
toolTip: $('#tool-tip'),
|
2020-08-12 15:10:23 +00:00
|
|
|
};
|
2020-08-06 14:41:38 +00:00
|
|
|
this.toggleSwitch = $('.theme-switch input[type="checkbox"]');
|
2020-11-03 08:01:33 +00:00
|
|
|
this.toggleSwitch.addEventListener('change', (e) => this.switchTheme(e));
|
|
|
|
this._view.logFileReader.addEventListener(
|
|
|
|
'fileuploadstart', (e) => this.handleFileUploadStart(e));
|
|
|
|
this._view.logFileReader.addEventListener(
|
|
|
|
'fileuploadend', (e) => this.handleFileUploadEnd(e));
|
2020-10-23 11:21:18 +00:00
|
|
|
this._startupPromise = this.runAsyncInitialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
async runAsyncInitialize() {
|
|
|
|
await Promise.all([
|
2020-12-07 08:44:54 +00:00
|
|
|
import('./view/list-panel.mjs'),
|
2020-11-18 15:51:07 +00:00
|
|
|
import('./view/timeline-panel.mjs'),
|
|
|
|
import('./view/map-panel.mjs'),
|
|
|
|
import('./view/source-panel.mjs'),
|
2020-12-01 19:37:17 +00:00
|
|
|
import('./view/code-panel.mjs'),
|
2020-11-26 14:07:19 +00:00
|
|
|
import('./view/tool-tip.mjs'),
|
2020-11-03 08:01:33 +00:00
|
|
|
]);
|
|
|
|
document.addEventListener(
|
|
|
|
'keydown', e => this._navigation?.handleKeyDown(e));
|
|
|
|
document.addEventListener(
|
|
|
|
SelectionEvent.name, e => this.handleShowEntries(e));
|
|
|
|
document.addEventListener(
|
2020-12-13 19:33:07 +00:00
|
|
|
FocusEvent.name, e => this.handleFocusLogEntryl(e));
|
2020-11-03 08:01:33 +00:00
|
|
|
document.addEventListener(
|
|
|
|
SelectTimeEvent.name, e => this.handleTimeRangeSelect(e));
|
2020-11-26 14:07:19 +00:00
|
|
|
document.addEventListener(ToolTipEvent.name, e => this.handleToolTip(e));
|
2020-07-23 08:41:38 +00:00
|
|
|
}
|
2020-10-23 11:21:18 +00:00
|
|
|
|
2020-08-12 15:10:23 +00:00
|
|
|
handleShowEntries(e) {
|
2020-12-03 17:48:45 +00:00
|
|
|
e.stopPropagation();
|
|
|
|
this.showEntries(e.entries);
|
|
|
|
}
|
|
|
|
|
|
|
|
showEntries(entries) {
|
2020-12-07 08:44:54 +00:00
|
|
|
groupBy(entries, each => each.constructor, true)
|
|
|
|
.forEach(group => this.showEntriesOfSingleType(group.entries));
|
2020-12-03 17:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
showEntriesOfSingleType(entries) {
|
|
|
|
switch (entries[0].constructor) {
|
|
|
|
case SourcePosition:
|
|
|
|
return this.showSourcePositions(entries);
|
|
|
|
case MapLogEntry:
|
|
|
|
return this.showMapEntries(entries);
|
|
|
|
case IcLogEntry:
|
|
|
|
return this.showIcEntries(entries);
|
|
|
|
case ApiLogEntry:
|
|
|
|
return this.showApiEntries(entries);
|
|
|
|
case CodeLogEntry:
|
|
|
|
return this.showCodeEntries(entries);
|
|
|
|
case DeoptLogEntry:
|
|
|
|
return this.showDeoptEntries(entries);
|
|
|
|
default:
|
|
|
|
throw new Error('Unknown selection type!');
|
2020-08-06 14:41:38 +00:00
|
|
|
}
|
2020-12-03 17:48:45 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 11:20:03 +00:00
|
|
|
showMapEntries(entries) {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._state.selectedMapLogEntries = entries;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.mapPanel.selectedLogEntries = entries;
|
|
|
|
this._view.mapList.selectedLogEntries = entries;
|
2020-08-13 11:20:03 +00:00
|
|
|
}
|
2020-11-30 10:34:28 +00:00
|
|
|
|
2020-08-13 11:20:03 +00:00
|
|
|
showIcEntries(entries) {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._state.selectedIcLogEntries = entries;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.icList.selectedLogEntries = entries;
|
2020-08-13 11:20:03 +00:00
|
|
|
}
|
2020-11-30 10:34:28 +00:00
|
|
|
|
2020-10-19 17:00:17 +00:00
|
|
|
showDeoptEntries(entries) {
|
|
|
|
this._state.selectedDeoptLogEntries = entries;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.deoptList.selectedLogEntries = entries;
|
2020-10-19 17:00:17 +00:00
|
|
|
}
|
2020-11-30 10:34:28 +00:00
|
|
|
|
|
|
|
showCodeEntries(entries) {
|
|
|
|
this._state.selectedCodeLogEntries = entries;
|
2020-12-01 19:37:17 +00:00
|
|
|
this._view.codePanel.selectedEntries = entries;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.codeList.selectedLogEntries = entries;
|
2020-11-30 10:34:28 +00:00
|
|
|
}
|
|
|
|
|
2020-12-03 17:48:45 +00:00
|
|
|
showApiEntries(entries) {
|
|
|
|
this._state.selectedApiLogEntries = entries;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.apiList.selectedLogEntries = entries;
|
2020-12-03 17:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
showSourcePositions(entries) {
|
2020-10-19 16:48:36 +00:00
|
|
|
this._view.sourcePanel.selectedSourcePositions = entries
|
2020-08-28 14:41:56 +00:00
|
|
|
}
|
2020-08-13 11:20:03 +00:00
|
|
|
|
2020-08-13 09:14:29 +00:00
|
|
|
handleTimeRangeSelect(e) {
|
|
|
|
this.selectTimeRange(e.start, e.end);
|
2020-10-19 17:00:17 +00:00
|
|
|
e.stopPropagation();
|
|
|
|
}
|
|
|
|
|
|
|
|
selectTimeRange(start, end) {
|
|
|
|
this._state.selectTimeRange(start, end);
|
2020-12-07 08:44:54 +00:00
|
|
|
this.showMapEntries(this._state.mapTimeline.selectionOrSelf);
|
|
|
|
this.showIcEntries(this._state.icTimeline.selectionOrSelf);
|
|
|
|
this.showDeoptEntries(this._state.deoptTimeline.selectionOrSelf);
|
|
|
|
this.showCodeEntries(this._state.codeTimeline.selectionOrSelf);
|
|
|
|
this.showApiEntries(this._state.apiTimeline.selectionOrSelf);
|
2020-11-03 08:01:33 +00:00
|
|
|
this._view.timelinePanel.timeSelection = {start, end};
|
2020-08-13 09:14:29 +00:00
|
|
|
}
|
2020-10-19 17:00:17 +00:00
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
handleFocusLogEntryl(e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
this.focusLogEntry(e.entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
focusLogEntry(entry) {
|
|
|
|
switch (entry.constructor) {
|
|
|
|
case SourcePosition:
|
|
|
|
return this.focusSourcePosition(entry);
|
|
|
|
case MapLogEntry:
|
|
|
|
return this.focusMapLogEntry(entry);
|
|
|
|
case IcLogEntry:
|
|
|
|
return this.focusIcLogEntry(entry);
|
|
|
|
case ApiLogEntry:
|
|
|
|
return this.focusApiLogEntry(entry);
|
|
|
|
case CodeLogEntry:
|
|
|
|
return this.focusCodeLogEntry(entry);
|
|
|
|
case DeoptLogEntry:
|
|
|
|
return this.focusDeoptLogEntry(entry);
|
|
|
|
default:
|
|
|
|
throw new Error('Unknown selection type!');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
focusMapLogEntry(entry) {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._state.map = entry;
|
2020-12-13 19:33:07 +00:00
|
|
|
this._view.mapTrack.focusedEntry = entry;
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = entry;
|
2020-08-04 08:51:59 +00:00
|
|
|
}
|
2020-11-30 10:34:28 +00:00
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
focusIcLogEntry(entry) {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._state.ic = entry;
|
2020-08-04 08:51:59 +00:00
|
|
|
}
|
2020-11-30 10:34:28 +00:00
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
focusCodeLogEntry(entry) {
|
2020-12-01 19:37:17 +00:00
|
|
|
this._state.code = entry;
|
|
|
|
this._view.codePanel.entry = entry;
|
|
|
|
}
|
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
focusDeoptLogEntry(entry) {
|
|
|
|
this._view.deoptList.focusedLogEntry = entry;
|
2020-12-03 17:48:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
focusApiLogEntry(entry) {
|
2020-12-03 17:48:45 +00:00
|
|
|
this._state.apiLogEntry = entry;
|
2020-12-13 19:33:07 +00:00
|
|
|
this._view.apiTrack.focusedEntry = entry;
|
2020-12-03 17:48:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 19:33:07 +00:00
|
|
|
focusSourcePosition(sourcePositions) {
|
2020-08-28 14:41:56 +00:00
|
|
|
if (!sourcePositions.script) return;
|
2020-12-13 19:33:07 +00:00
|
|
|
this._view.sourcePanel.focusedSourcePositions = [sourcePositions];
|
2020-08-04 08:51:59 +00:00
|
|
|
}
|
2020-08-28 14:41:56 +00:00
|
|
|
|
2020-11-26 14:07:19 +00:00
|
|
|
handleToolTip(event) {
|
|
|
|
this._view.toolTip.positionOrTargetNode = event.positionOrTargetNode;
|
|
|
|
this._view.toolTip.content = event.content;
|
|
|
|
}
|
|
|
|
|
2020-10-19 16:48:36 +00:00
|
|
|
handleFileUploadStart(e) {
|
2020-08-27 17:51:33 +00:00
|
|
|
this.restartApp();
|
2020-11-03 08:01:33 +00:00
|
|
|
$('#container').className = 'initial';
|
2020-07-16 10:02:52 +00:00
|
|
|
}
|
2020-10-19 10:13:33 +00:00
|
|
|
|
2020-08-27 17:51:33 +00:00
|
|
|
restartApp() {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._state = new State();
|
|
|
|
this._navigation = new Navigation(this._state, this._view);
|
2020-08-27 17:51:33 +00:00
|
|
|
}
|
2020-10-19 10:13:33 +00:00
|
|
|
|
2020-10-23 11:21:18 +00:00
|
|
|
async handleFileUploadEnd(e) {
|
|
|
|
await this._startupPromise;
|
|
|
|
try {
|
|
|
|
const processor = new Processor(e.detail);
|
2020-12-14 09:41:32 +00:00
|
|
|
this._state.profile = processor.profile;
|
2020-10-23 11:21:18 +00:00
|
|
|
const mapTimeline = processor.mapTimeline;
|
|
|
|
const icTimeline = processor.icTimeline;
|
|
|
|
const deoptTimeline = processor.deoptTimeline;
|
2020-11-30 10:34:28 +00:00
|
|
|
const codeTimeline = processor.codeTimeline;
|
2020-12-03 17:48:45 +00:00
|
|
|
const apiTimeline = processor.apiTimeline;
|
2020-11-30 10:34:28 +00:00
|
|
|
this._state.setTimelines(
|
2020-12-03 17:48:45 +00:00
|
|
|
mapTimeline, icTimeline, deoptTimeline, codeTimeline, apiTimeline);
|
2020-10-23 11:21:18 +00:00
|
|
|
this._view.mapPanel.timeline = mapTimeline;
|
2020-12-07 08:44:54 +00:00
|
|
|
this._view.icList.timeline = icTimeline;
|
|
|
|
this._view.mapList.timeline = mapTimeline;
|
|
|
|
this._view.deoptList.timeline = deoptTimeline;
|
|
|
|
this._view.codeList.timeline = codeTimeline;
|
|
|
|
this._view.apiList.timeline = apiTimeline;
|
2020-11-30 12:32:49 +00:00
|
|
|
this._view.sourcePanel.data = processor.scripts;
|
2020-12-01 19:37:17 +00:00
|
|
|
this._view.codePanel.timeline = codeTimeline;
|
2020-11-30 12:32:49 +00:00
|
|
|
this.refreshTimelineTrackView();
|
2020-11-03 08:01:33 +00:00
|
|
|
} catch (e) {
|
|
|
|
this._view.logFileReader.error = 'Log file contains errors!'
|
|
|
|
throw (e);
|
2020-11-02 09:27:28 +00:00
|
|
|
} finally {
|
2020-11-03 08:01:33 +00:00
|
|
|
$('#container').className = 'loaded';
|
2020-11-02 09:27:28 +00:00
|
|
|
this.fileLoaded = true;
|
2020-10-23 11:21:18 +00:00
|
|
|
}
|
2020-07-16 10:02:52 +00:00
|
|
|
}
|
2020-07-14 15:03:14 +00:00
|
|
|
|
2020-08-12 15:10:23 +00:00
|
|
|
refreshTimelineTrackView() {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.data = this._state.mapTimeline;
|
|
|
|
this._view.icTrack.data = this._state.icTimeline;
|
2020-10-19 16:48:36 +00:00
|
|
|
this._view.deoptTrack.data = this._state.deoptTimeline;
|
2020-11-30 10:34:28 +00:00
|
|
|
this._view.codeTrack.data = this._state.codeTimeline;
|
2020-12-03 17:48:45 +00:00
|
|
|
this._view.apiTrack.data = this._state.apiTimeline;
|
2020-08-05 04:13:01 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 09:02:26 +00:00
|
|
|
switchTheme(event) {
|
2020-11-03 08:01:33 +00:00
|
|
|
document.documentElement.dataset.theme =
|
|
|
|
event.target.checked ? 'light' : 'dark';
|
2020-11-16 13:19:25 +00:00
|
|
|
CSSColor.reset();
|
|
|
|
if (!this.fileLoaded) return;
|
|
|
|
this.refreshTimelineTrackView();
|
2020-07-28 09:02:26 +00:00
|
|
|
}
|
2020-07-15 07:28:00 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 07:35:23 +00:00
|
|
|
class Navigation {
|
2020-10-19 10:45:42 +00:00
|
|
|
_view;
|
2020-08-13 07:35:23 +00:00
|
|
|
constructor(state, view) {
|
|
|
|
this.state = state;
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view = view;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
get map() {
|
|
|
|
return this.state.map
|
|
|
|
}
|
|
|
|
set map(value) {
|
|
|
|
this.state.map = value
|
|
|
|
}
|
|
|
|
get chunks() {
|
2020-10-19 16:48:36 +00:00
|
|
|
return this.state.mapTimeline.chunks;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
increaseTimelineResolution() {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.timelinePanel.nofChunks *= 1.5;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.state.nofChunks *= 1.5;
|
|
|
|
}
|
|
|
|
decreaseTimelineResolution() {
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.timelinePanel.nofChunks /= 1.5;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.state.nofChunks /= 1.5;
|
|
|
|
}
|
|
|
|
selectNextEdge() {
|
|
|
|
if (!this.map) return;
|
|
|
|
if (this.map.children.length != 1) return;
|
|
|
|
this.map = this.map.children[0].to;
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.selectedEntry = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.updateUrl();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
selectPrevEdge() {
|
|
|
|
if (!this.map) return;
|
|
|
|
if (!this.map.parent()) return;
|
|
|
|
this.map = this.map.parent();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.selectedEntry = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.updateUrl();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
selectDefaultMap() {
|
|
|
|
this.map = this.chunks[0].at(0);
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.selectedEntry = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.updateUrl();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
moveInChunks(next) {
|
|
|
|
if (!this.map) return this.selectDefaultMap();
|
|
|
|
let chunkIndex = this.map.chunkIndex(this.chunks);
|
|
|
|
let chunk = this.chunks[chunkIndex];
|
|
|
|
let index = chunk.indexOf(this.map);
|
|
|
|
if (next) {
|
|
|
|
chunk = chunk.next(this.chunks);
|
|
|
|
} else {
|
|
|
|
chunk = chunk.prev(this.chunks);
|
|
|
|
}
|
|
|
|
if (!chunk) return;
|
|
|
|
index = Math.min(index, chunk.size() - 1);
|
|
|
|
this.map = chunk.at(index);
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.selectedEntry = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.updateUrl();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
moveInChunk(delta) {
|
|
|
|
if (!this.map) return this.selectDefaultMap();
|
|
|
|
let chunkIndex = this.map.chunkIndex(this.chunks)
|
|
|
|
let chunk = this.chunks[chunkIndex];
|
|
|
|
let index = chunk.indexOf(this.map) + delta;
|
|
|
|
let map;
|
|
|
|
if (index < 0) {
|
|
|
|
map = chunk.prev(this.chunks).last();
|
|
|
|
} else if (index >= chunk.size()) {
|
|
|
|
map = chunk.next(this.chunks).first()
|
|
|
|
} else {
|
|
|
|
map = chunk.at(index);
|
|
|
|
}
|
|
|
|
this.map = map;
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapTrack.selectedEntry = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
this.updateUrl();
|
2020-10-19 10:45:42 +00:00
|
|
|
this._view.mapPanel.map = this.map;
|
2020-08-13 07:35:23 +00:00
|
|
|
}
|
|
|
|
updateUrl() {
|
|
|
|
let entries = this.state.entries;
|
|
|
|
let params = new URLSearchParams(entries);
|
|
|
|
window.history.pushState(entries, '', '?' + params.toString());
|
|
|
|
}
|
|
|
|
handleKeyDown(event) {
|
|
|
|
switch (event.key) {
|
2020-11-03 08:01:33 +00:00
|
|
|
case 'ArrowUp':
|
2020-08-13 07:35:23 +00:00
|
|
|
event.preventDefault();
|
|
|
|
if (event.shiftKey) {
|
|
|
|
this.selectPrevEdge();
|
|
|
|
} else {
|
|
|
|
this.moveInChunk(-1);
|
|
|
|
}
|
|
|
|
return false;
|
2020-11-03 08:01:33 +00:00
|
|
|
case 'ArrowDown':
|
2020-08-13 07:35:23 +00:00
|
|
|
event.preventDefault();
|
|
|
|
if (event.shiftKey) {
|
|
|
|
this.selectNextEdge();
|
|
|
|
} else {
|
|
|
|
this.moveInChunk(1);
|
|
|
|
}
|
|
|
|
return false;
|
2020-11-03 08:01:33 +00:00
|
|
|
case 'ArrowLeft':
|
2020-08-13 07:35:23 +00:00
|
|
|
this.moveInChunks(false);
|
|
|
|
break;
|
2020-11-03 08:01:33 +00:00
|
|
|
case 'ArrowRight':
|
2020-08-13 07:35:23 +00:00
|
|
|
this.moveInChunks(true);
|
|
|
|
break;
|
2020-11-03 08:01:33 +00:00
|
|
|
case '+':
|
2020-08-13 07:35:23 +00:00
|
|
|
this.increaseTimelineResolution();
|
|
|
|
break;
|
2020-11-03 08:01:33 +00:00
|
|
|
case '-':
|
2020-08-13 07:35:23 +00:00
|
|
|
this.decreaseTimelineResolution();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 08:01:33 +00:00
|
|
|
export {App};
|