Commit 34b65260 authored by Zeynep Cankara's avatar Zeynep Cankara Committed by Commit Bot

[tools][system-analyzer] Change naming conventions

This CL establishes a naming consistency
across the app by renaming classes.

Class Name Changes:
SelectEvent -> FocusEvent
Entry -> IcLogEvent
V8Map -> MapLogEvent

Bug: v8:10644
Change-Id: Id075d9aa36ac6f03af0224feb0e38985b1445013
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2349300
Commit-Queue: Zeynep Cankara <zcankara@google.com>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69382}
parent 279bd3e1
// 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.
class SelectionEvent extends CustomEvent {
static name = "showentries";
constructor(entries) {
super('showentries', { bubbles: true, composed: true });
super(SelectionEvent.name, { bubbles: true, composed: true });
if (!Array.isArray(entries) || entries.length == 0) {
throw new Error('No valid entries selected!')
throw new Error("No valid entries selected!");
}
this.entries = entries;
}
}
class SelectEvent extends CustomEvent {
class FocusEvent extends CustomEvent {
static name = "showentrydetail";
constructor(entry) {
super('showentrydetail', { bubbles: true, composed: true });
super(FocusEvent.name, { bubbles: true, composed: true });
this.entry = entry;
}
}
......@@ -29,4 +30,4 @@ class SelectTimeEvent extends CustomEvent {
}
}
export { SelectionEvent, SelectEvent, SelectTimeEvent };
export { SelectionEvent, FocusEvent, SelectTimeEvent };
......@@ -44,12 +44,20 @@ found in the LICENSE file. -->
#legend {
padding-right: 20px;
}
dl {
float: right;
border-style: solid;
border-width: 1px;
padding: 20px;
}
</style>
<div class="panel">
<h2>IC Panel</h2>
<h3>IC Explorer</h3>
<div id="legend">
<dl style="float:right; border-style: solid; border-width: 1px; padding:20px">
<dl>
<dt>0</dt>
<dd>uninitialized</dd>
<dt>X</dt>
......@@ -79,7 +87,8 @@ found in the LICENSE file. -->
<p>
Filter by Time
<br></br>
<input type="search" id="filter-time-start" placeholder="start"></input> : <input type="search" id="filter-time-end" placeholder="end"></input>
<input type="search" id="filter-time-start" placeholder="start"></input> :
<input type="search" id="filter-time-end" placeholder="end"></input>
<button id="filterICTimeBtn">Filter</button>
<p>
<table id="table" width="100%">
......
......@@ -4,7 +4,7 @@
import { Group } from './ic-model.mjs';
import CustomIcProcessor from "./ic-processor.mjs";
import { SelectEvent, SelectTimeEvent } from './events.mjs';
import { FocusEvent, SelectTimeEvent } from './events.mjs';
import { defineCustomElement, V8CustomElement } from './helper.mjs';
defineCustomElement('ic-panel', (templateText) =>
......@@ -93,11 +93,11 @@ defineCustomElement('ic-panel', (templateText) =>
}
handleMapClick(e) {
this.dispatchEvent(new SelectEvent(e.target.parentNode.entry));
this.dispatchEvent(new FocusEvent(e.target.parentNode.entry));
}
handleFilePositionClick(e) {
this.dispatchEvent(new SelectEvent(e.target.parentNode.entry.key));
this.dispatchEvent(new FocusEvent(e.target.parentNode.entry.key));
}
render(entries, parent) {
......
......@@ -209,7 +209,7 @@ class CustomIcProcessor extends IcProcessor {
type, pc, time, line, column, old_state, new_state, map, key, modifier,
slow_reason) {
let fnName = this.functionName(pc);
let entry = new Entry(
let entry = new IcLogEvent(
type, fnName, time, line, column, key, old_state, new_state, map,
slow_reason);
this.#timeline.push(entry);
......@@ -225,8 +225,8 @@ class CustomIcProcessor extends IcProcessor {
return this.timeline;
}
};
// TODO(zcankara) Change name to Entry -> V8IcEntry or V8Ic
class Entry extends Event {
class IcLogEvent extends Event {
constructor(
type, fn_file, time, line, column, key, oldState, newState, map, reason,
additional) {
......@@ -279,4 +279,4 @@ class Entry extends Event {
}
}
export { CustomIcProcessor as default, Entry};
export { CustomIcProcessor as default, IcLogEvent};
......@@ -23,95 +23,101 @@ found in the LICENSE file. -->
<script src="../logreader.js"></script>
<script src="../arguments.js"></script>
<script src="../SourceMap.js"></script>
<style>
#instructions {
padding: 10px 10px 60px 10px ;
margin: auto;
}
kbd {
background-color: var(--primary-color);
color: var(--on-primary-color);
border-radius: 3px;
border: 1px solid var(--on-primary-color);
display: inline-block;
font-size: .9em;
font-weight: bold;
padding: 0px 4px 2px 4px;
white-space: nowrap;
}
/*Simple css to style it like a toggle switch*/
.theme-switch-wrapper {
display: flex;
align-items: center;
}
.theme-switch {
display: inline-block;
height: 34px;
position: relative;
width: 60px;
}
.theme-switch input {
display:none;
}
.slider {
background-color: var(--primary-color);
bottom: 0;
cursor: pointer;
left: 0;
position: absolute;
right: 0;
top: 0;
transition: .4s;
}
.slider:before {
background-color: var(--surface-color);
bottom: 4px;
content: "";
height: 26px;
left: 4px;
position: absolute;
transition: .4s;
width: 26px;
}
input:checked + .slider {
background-color: var(--primary-color);
}
input:checked + .slider:before {
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
#container.initial {
display: none;
}
#container.loaded {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
grid-auto-flow: dense;
}
#container.loaded > #timeline-panel {
grid-column: span 2;
}
</style>
<script type="module" >
import {App} from './index.mjs';
globalThis.app = new App("#log-file-reader", "#map-panel", "#timeline-panel",
"#ic-panel", "#map-track", "#ic-track");
</script>
<style>
#instructions {
padding: 10px 10px 60px 10px;
margin: auto;
}
kbd {
background-color: var(--primary-color);
color: var(--on-primary-color);
border-radius: 3px;
border: 1px solid var(--on-primary-color);
display: inline-block;
font-size: .9em;
font-weight: bold;
padding: 0px 4px 2px 4px;
white-space: nowrap;
}
/*Simple css to style it like a toggle switch*/
.theme-switch-wrapper {
display: flex;
align-items: center;
}
.theme-switch {
display: inline-block;
height: 34px;
position: relative;
width: 60px;
}
.theme-switch input {
display: none;
}
.slider {
background-color: var(--primary-color);
bottom: 0;
cursor: pointer;
left: 0;
position: absolute;
right: 0;
top: 0;
transition: .4s;
}
.slider:before {
background-color: var(--surface-color);
bottom: 4px;
content: "";
height: 26px;
left: 4px;
position: absolute;
transition: .4s;
width: 26px;
}
input:checked+.slider {
background-color: var(--primary-color);
}
input:checked+.slider:before {
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
#container.initial {
display: none;
}
#container.loaded {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
grid-auto-flow: dense;
}
#container.loaded>#timeline-panel {
grid-column: span 2;
}
</style>
<script type="module">
import { App } from './index.mjs';
globalThis.app = new App("#log-file-reader", "#map-panel", "#timeline-panel",
"#ic-panel", "#map-track", "#ic-track");
</script>
</head>
<body>
<div id="content">
<section id="file-reader">
......@@ -130,7 +136,7 @@ globalThis.app = new App("#log-file-reader", "#map-panel", "#timeline-panel",
</div>
<div class="theme-switch-wrapper">
<label class="theme-switch" for="checkbox">
<input type="checkbox" id="checkbox"/>
<input type="checkbox" id="checkbox" />
<div class="slider round"></div>
</label>
</div>
......@@ -173,4 +179,5 @@ globalThis.app = new App("#log-file-reader", "#map-panel", "#timeline-panel",
</dl>
</div>
</body>
</html>
......@@ -3,9 +3,10 @@
// found in the LICENSE file.
import CustomIcProcessor from "./ic-processor.mjs";
import { Entry } from "./ic-processor.mjs";
import { SelectionEvent, FocusEvent } from "./events.mjs";
import { IcLogEvent } from "./ic-processor.mjs";
import { State } from "./app-model.mjs";
import { MapProcessor, V8Map } from "./map-processor.mjs";
import { MapProcessor, MapLogEvent } from "./map-processor.mjs";
import { SelectTimeEvent } from "./events.mjs";
import { $ } from "./helper.mjs";
import "./ic-panel.mjs";
......@@ -38,19 +39,19 @@ class App {
this.#view.logFileReader.addEventListener("fileuploadend", (e) =>
this.handleDataUpload(e)
);
Object.entries(this.#view).forEach(([_, value]) => {
value.addEventListener('showentries',
Object.entries(this.#view).forEach(([_, panel]) => {
panel.addEventListener(SelectionEvent.name,
e => this.handleShowEntries(e));
value.addEventListener('showentrydetail',
panel.addEventListener(FocusEvent.name,
e => this.handleShowEntryDetail(e));
value.addEventListener(SelectTimeEvent.name,
panel.addEventListener(SelectTimeEvent.name,
e => this.handleTimeRangeSelect(e));
});
}
handleShowEntries(e) {
if (e.entries[0] instanceof V8Map) {
if (e.entries[0] instanceof MapLogEvent) {
this.showMapEntries(e.entries);
} else if (e.entries[0] instanceof Entry) {
} else if (e.entries[0] instanceof IcLogEvent) {
this.showIcEntries(e.entries);
} else {
console.error("Undefined selection!");
......@@ -70,9 +71,9 @@ class App {
this.selectTimeRange(e.start, e.end);
}
handleShowEntryDetail(e) {
if (e.entry instanceof V8Map) {
if (e.entry instanceof MapLogEvent) {
this.selectMapLogEvent(e.entry);
} else if (e.entry instanceof Entry) {
} else if (e.entry instanceof IcLogEvent) {
this.selectICLogEvent(e.entry);
} else if (typeof e.entry === 'string') {
this.selectSourcePositionEvent(e.entry);
......@@ -89,7 +90,8 @@ class App {
this.#state.timeSelection.end = end;
this.#state.icTimeline.selectTimeRange(start, end);
this.#state.mapTimeline.selectTimeRange(start, end);
this.#view.mapPanel.selectedMapLogEvents = this.#state.mapTimeline.selection;
this.#view.mapPanel.selectedMapLogEvents =
this.#state.mapTimeline.selection;
this.#view.icPanel.filteredEntries = this.#state.icTimeline.selection;
}
selectMapLogEvent(entry) {
......
......@@ -11,7 +11,8 @@ defineCustomElement('log-file-reader', (templateText) =>
this.addEventListener('dragover', e => this.handleDragOver(e));
this.addEventListener('drop', e => this.handleChange(e));
this.$('#file').addEventListener('change', e => this.handleChange(e));
this.$('#fileReader').addEventListener('keydown', e => this.handleKeyEvent(e));
this.$('#fileReader').addEventListener('keydown',
e => this.handleKeyEvent(e));
}
get section() {
......
......@@ -15,7 +15,8 @@ found in the LICENSE file. -->
<map-transitions id="map-transitions"></map-transitions>
<h3>Search Map by Address</h3>
<section id="searchBar"></section>
<input type="search" id="searchBarInput" placeholder="Search maps by address.."></input>
<input type="search" id="searchBarInput"
placeholder="Search maps by address.."></input>
<button id="searchBarBtn">Search</button>
<map-details id="map-details"></map-details>
......
......@@ -4,8 +4,8 @@
import "./stats-panel.mjs";
import "./map-panel/map-details.mjs";
import "./map-panel/map-transitions.mjs";
import { SelectEvent } from './events.mjs';
import { V8Map } from "./map-processor.mjs";
import { FocusEvent } from './events.mjs';
import { MapLogEvent } from "./map-processor.mjs";
import { defineCustomElement, V8CustomElement } from './helper.mjs';
defineCustomElement('map-panel', (templateText) =>
......@@ -16,11 +16,13 @@ defineCustomElement('map-panel', (templateText) =>
this.searchBarBtn.addEventListener(
'click', e => this.handleSearchBar(e));
this.addEventListener(
'mapdetailsupdate', e => this.handleUpdateMapDetails(e));
FocusEvent.name, e => this.handleUpdateMapDetails(e));
}
handleUpdateMapDetails(e) {
this.mapDetailsPanel.mapDetails = e.detail;
if (e.entry instanceof MapLogEvent) {
this.mapDetailsPanel.mapDetails = e.entry;
}
}
get statsPanel() {
......@@ -72,13 +74,13 @@ defineCustomElement('map-panel', (templateText) =>
let searchBar = this.$('#searchBarInput');
let searchBarInput = searchBar.value;
//access the map from model cache
let selectedMap = V8Map.get(searchBarInput);
let selectedMap = MapLogEvent.get(searchBarInput);
if (selectedMap) {
searchBar.className = "success";
} else {
searchBar.className = "failure";
}
this.dispatchEvent(new SelectEvent(selectedMap));
this.dispatchEvent(new FocusEvent(selectedMap));
}
set selectedMapLogEvents(list) {
......
// 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.
import {V8CustomElement, defineCustomElement} from '../helper.mjs';
import {SelectEvent} from '../events.mjs';
import { V8CustomElement, defineCustomElement } from "../helper.mjs";
import { FocusEvent } from "../events.mjs";
defineCustomElement('./map-panel/map-details', (templateText) =>
class MapDetails extends V8CustomElement {
constructor() {
super(templateText);
this.mapDetails.addEventListener('click', () => this.handleClickSourcePositions());
this.selectedMap = undefined;
}
get mapDetails() {
return this.$('#mapDetails');
}
defineCustomElement(
"./map-panel/map-details",
(templateText) =>
class MapDetails extends V8CustomElement {
constructor() {
super(templateText);
this.mapDetails.addEventListener("click", () =>
this.handleClickSourcePositions()
);
this.selectedMap = undefined;
}
get mapDetails() {
return this.$("#mapDetails");
}
setSelectedMap(value) {
this.selectedMap = value;
}
setSelectedMap(value) {
this.selectedMap = value;
}
set mapDetails(map){
let details = '';
if (map) {
details += 'ID: ' + map.id;
details += '\nSource location: ' + map.filePosition;
details += '\n' + map.description;
this.setSelectedMap(map);
}
this.mapDetails.innerText = details;
}
set mapDetails(map) {
let details = "";
if (map) {
details += "ID: " + map.id;
details += "\nSource location: " + map.filePosition;
details += "\n" + map.description;
this.setSelectedMap(map);
}
this.mapDetails.innerText = details;
}
handleClickSourcePositions(){
this.dispatchEvent(new SelectEvent(this.selectedMap.filePosition));
}
});
handleClickSourcePositions() {
this.dispatchEvent(new FocusEvent(this.selectedMap.filePosition));
}
}
);
......@@ -236,14 +236,14 @@ class MapProcessor extends LogReader {
}
createMap(id, time) {
let map = new V8Map(id, time);
let map = new MapLogEvent(id, time);
this.#timeline.push(map);
return map;
}
getExistingMap(id, time) {
if (id === '0x000000000000') return undefined;
let map = V8Map.get(id, time);
let map = MapLogEvent.get(id, time);
if (map === undefined) {
console.error('No map details provided: id=' + id);
// Manually patch in a map to continue running.
......@@ -255,7 +255,7 @@ class MapProcessor extends LogReader {
// ===========================================================================
class V8Map extends Event {
class MapLogEvent extends Event {
edge = void 0;
children = [];
depth = 0;
......@@ -269,7 +269,7 @@ class V8Map extends Event {
constructor(id, time) {
if (!time) throw new Error('Invalid time');
super(id, time);
V8Map.set(id, this);
MapLogEvent.set(id, this);
this.id = id;
}
......@@ -393,7 +393,7 @@ class V8Map extends Event {
}
}
V8Map.cache = new Map();
MapLogEvent.cache = new Map();
// ===========================================================================
class Edge {
......@@ -535,4 +535,4 @@ class ArgumentsProcessor extends BaseArgumentsProcessor {
}
}
export { MapProcessor, V8Map, kChunkWidth, kChunkHeight};
export { MapProcessor, MapLogEvent, kChunkWidth, kChunkHeight};
// 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.
import {V8CustomElement, defineCustomElement} from './helper.mjs';
import {SelectionEvent} from './events.mjs';
import { V8CustomElement, defineCustomElement } from "./helper.mjs";
import { SelectionEvent } from "./events.mjs";
defineCustomElement('stats-panel', (templateText) =>
class StatsPanel extends V8CustomElement {
#timeline;
#transitions;
constructor() {
super(templateText);
}
defineCustomElement(
"stats-panel",
(templateText) =>
class StatsPanel extends V8CustomElement {
#timeline;
#transitions;
constructor() {
super(templateText);
}
get stats() {
return this.$('#stats');
}
get stats() {
return this.$("#stats");
}
set timeline(value){
//TODO(zcankara) Trigger update
this.#timeline = value;
}
set timeline(value) {
//TODO(zcankara) Trigger update
this.#timeline = value;
}
get timeline(){
return this.#timeline;
}
get timeline() {
return this.#timeline;
}
set transitions(value){
this.#transitions = value;
}
set transitions(value) {
this.#transitions = value;
}
get transitions(){
return this.#transitions;
}
get transitions() {
return this.#transitions;
}
filterUniqueTransitions(filter) {
// Returns a list of Maps whose parent is not in the list.
return this.timeline.filter(map => {
if (filter(map) === false) return false;
let parent = map.parent();
if (parent === undefined) return true;
return filter(parent) === false;
});
}
filterUniqueTransitions(filter) {
// Returns a list of Maps whose parent is not in the list.
return this.timeline.filter((map) => {
if (filter(map) === false) return false;
let parent = map.parent();
if (parent === undefined) return true;
return filter(parent) === false;
});
}
update() {
this.removeAllChildren(this.stats);
this.updateGeneralStats();
this.updateNamedTransitionsStats();
}
update() {
this.removeAllChildren(this.stats);
this.updateGeneralStats();
this.updateNamedTransitionsStats();
}
updateGeneralStats() {
console.assert(this.#timeline !== undefined, "Timeline not set yet!");
let pairs = [
['Total', null, e => true],
['Transitions', 'primary', e => e.edge && e.edge.isTransition()],
['Fast to Slow', 'violet', e => e.edge && e.edge.isFastToSlow()],
['Slow to Fast', 'orange', e => e.edge && e.edge.isSlowToFast()],
['Initial Map', 'yellow', e => e.edge && e.edge.isInitial()],
[
'Replace Descriptors', 'red',
e => e.edge && e.edge.isReplaceDescriptors()
],
['Copy as Prototype', 'red', e => e.edge && e.edge.isCopyAsPrototype()],
[
'Optimize as Prototype', null,
e => e.edge && e.edge.isOptimizeAsPrototype()
],
['Deprecated', null, e => e.isDeprecated()],
['Bootstrapped', 'green', e => e.isBootstrapped()],
];
updateGeneralStats() {
console.assert(this.#timeline !== undefined, "Timeline not set yet!");
let pairs = [
["Total", null, (e) => true],
["Transitions", "primary", (e) => e.edge && e.edge.isTransition()],
["Fast to Slow", "violet", (e) => e.edge && e.edge.isFastToSlow()],
["Slow to Fast", "orange", (e) => e.edge && e.edge.isSlowToFast()],
["Initial Map", "yellow", (e) => e.edge && e.edge.isInitial()],
[
"Replace Descriptors",
"red",
(e) => e.edge && e.edge.isReplaceDescriptors(),
],
[
"Copy as Prototype",
"red",
(e) => e.edge && e.edge.isCopyAsPrototype(),
],
[
"Optimize as Prototype",
null,
(e) => e.edge && e.edge.isOptimizeAsPrototype(),
],
["Deprecated", null, (e) => e.isDeprecated()],
["Bootstrapped", "green", (e) => e.isBootstrapped()],
];
let text = '';
let tableNode = this.table('transitionType');
tableNode.innerHTML =
'<thead><tr><td>Color</td><td>Type</td><td>Count</td><td>Percent</td></tr></thead>';
let name, filter;
let total = this.timeline.size();
pairs.forEach(([name, color, filter]) => {
let row = this.tr();
if (color !== null) {
row.appendChild(this.td(this.div(['colorbox', color])));
} else {
row.appendChild(this.td(''));
let text = "";
let tableNode = this.table("transitionType");
tableNode.innerHTML =
"<thead><tr><td>Color</td><td>Type</td><td>Count</td><td>Percent</td></tr></thead>";
let name, filter;
let total = this.timeline.size();
pairs.forEach(([name, color, filter]) => {
let row = this.tr();
if (color !== null) {
row.appendChild(this.td(this.div(["colorbox", color])));
} else {
row.appendChild(this.td(""));
}
row.onclick = (e) => {
// lazily compute the stats
let node = e.target.parentNode;
if (node.maps == undefined) {
node.maps = this.filterUniqueTransitions(filter);
}
this.dispatchEvent(new SelectionEvent(node.maps));
};
row.appendChild(this.td(name));
let count = this.timeline.count(filter);
row.appendChild(this.td(count));
let percent = Math.round((count / total) * 1000) / 10;
row.appendChild(this.td(percent.toFixed(1) + "%"));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
row.onclick = (e) => {
// lazily compute the stats
let node = e.target.parentNode;
if (node.maps == undefined) {
node.maps = this.filterUniqueTransitions(filter);
}
this.dispatchEvent(new SelectionEvent(node.maps));
};
row.appendChild(this.td(name));
let count = this.timeline.count(filter);
row.appendChild(this.td(count));
let percent = Math.round(count / total * 1000) / 10;
row.appendChild(this.td(percent.toFixed(1) + '%'));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
updateNamedTransitionsStats() {
let tableNode = this.table('transitionTable');
let nameMapPairs = Array.from(this.transitions.entries());
tableNode.innerHTML =
'<thead><tr><td>Propery Name</td><td>#</td></tr></thead>';
nameMapPairs.sort((a, b) => b[1].length - a[1].length).forEach(([
name, maps
]) => {
let row = this.tr();
row.maps = maps;
row.addEventListener(
'click',
e => this.dispatchEvent(
new SelectionEvent(e.target.parentNode.maps.map(map => map.to))));
row.appendChild(this.td(name));
row.appendChild(this.td(maps.length));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
});
updateNamedTransitionsStats() {
let tableNode = this.table("transitionTable");
let nameMapPairs = Array.from(this.transitions.entries());
tableNode.innerHTML =
"<thead><tr><td>Propery Name</td><td>#</td></tr></thead>";
nameMapPairs
.sort((a, b) => b[1].length - a[1].length)
.forEach(([name, maps]) => {
let row = this.tr();
row.maps = maps;
row.addEventListener("click", (e) =>
this.dispatchEvent(
new SelectionEvent(
e.target.parentNode.maps.map((map) => map.to)
)
)
);
row.appendChild(this.td(name));
row.appendChild(this.td(maps.length));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
}
);
......@@ -7,7 +7,7 @@ import {
transitionTypeToColor, CSSColor
} from '../helper.mjs';
import { kChunkWidth, kChunkHeight } from '../map-processor.mjs';
import { SelectionEvent, SelectEvent, SelectTimeEvent } from '../events.mjs';
import { SelectionEvent, FocusEvent, SelectTimeEvent } from '../events.mjs';
defineCustomElement('./timeline/timeline-track', (templateText) =>
class TimelineTrack extends V8CustomElement {
......@@ -254,7 +254,7 @@ defineCustomElement('./timeline/timeline-track', (templateText) =>
let relativeIndex =
Math.round(event.layerY / event.target.offsetHeight * chunk.size());
let map = chunk.at(relativeIndex);
this.dispatchEvent(new SelectEvent(map));
this.dispatchEvent(new FocusEvent(map));
}
handleChunkClick(event) {
......@@ -265,7 +265,7 @@ defineCustomElement('./timeline/timeline-track', (templateText) =>
this.isLocked = true;
let chunk = event.target.chunk;
if (!chunk) return;
let maps = chunk.filter();
let maps = chunk.items;
this.dispatchEvent(new SelectionEvent(maps));
}
......@@ -292,7 +292,10 @@ defineCustomElement('./timeline/timeline-track', (templateText) =>
ctx.fill();
let imageData = canvas.toDataURL('image/webp', 0.2);
this.dispatchEvent(new CustomEvent(
'overviewupdate', { bubbles: true, composed: true, detail: imageData }));
'overviewupdate', {
bubbles: true, composed: true,
detail: imageData
}));
}
redraw() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment