Commit 8b338b25 authored by Zeynep Cankara's avatar Zeynep Cankara Committed by Commit Bot

[tools][system-analyzer] Add Transition View logic to Map Panel

This CL depreciates the TransitionView Class of the
app model to handle map transition only within map
model. It isolates the Map Panel to comply web
component standards.

Bug: v8:10667, v8:10644

Change-Id: Idf8ca58744aacd0159ee4af6e71886374385377e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2300541
Commit-Queue: Zeynep Cankara <zcankara@google.com>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68902}
parent 3c1bf982
...@@ -105,8 +105,8 @@ class App { ...@@ -105,8 +105,8 @@ class App {
} }
handleShowMaps(e) { handleShowMaps(e) {
// show maps on the view //document.state.view.transitionView.showMaps(e.detail);
document.state.view.transitionView.showMaps(e.detail); document.state.mapPanel.showMaps(e.detail);
} }
handleSelectIc(e){ handleSelectIc(e){
......
...@@ -14,6 +14,8 @@ class State { ...@@ -14,6 +14,8 @@ class State {
this._timeline = undefined; this._timeline = undefined;
this._chunks = undefined; this._chunks = undefined;
this._view = new View(this, mapPanelId, timelinePanelId); this._view = new View(this, mapPanelId, timelinePanelId);
//TODO(zcankara) Depreciate the view
this.mapPanel_ = $(mapPanelId);
this._navigation = new Navigation(this, this.view); this._navigation = new Navigation(this, this.view);
} }
set filteredEntries(value) { set filteredEntries(value) {
...@@ -32,7 +34,7 @@ class State { ...@@ -32,7 +34,7 @@ class State {
this._timeline = value; this._timeline = value;
this.updateChunks(); this.updateChunks();
this.view.updateTimeline(); this.view.updateTimeline();
this.view.updateStats(); this.mapPanel_.updateStats(this.timeline);
} }
get chunks() { get chunks() {
return this._chunks return this._chunks
...@@ -45,6 +47,9 @@ class State { ...@@ -45,6 +47,9 @@ class State {
this.updateChunks(); this.updateChunks();
this.view.updateTimeline(); this.view.updateTimeline();
} }
get mapPanel() {
return this.mapPanel_;
}
get view() { get view() {
return this._view return this._view
} }
...@@ -57,7 +62,7 @@ class State { ...@@ -57,7 +62,7 @@ class State {
set map(value) { set map(value) {
this._map = value; this._map = value;
this._navigation.updateUrl(); this._navigation.updateUrl();
this.view.updateMapDetails(); this.mapPanel_.showMap(this.map);
this.view.redraw(); this.view.redraw();
} }
updateChunks() { updateChunks() {
...@@ -154,8 +159,9 @@ class View { ...@@ -154,8 +159,9 @@ class View {
this.state = state; this.state = state;
setInterval(this.updateOverviewWindow(timelinePanelId), 50); setInterval(this.updateOverviewWindow(timelinePanelId), 50);
this.backgroundCanvas = document.createElement('canvas'); this.backgroundCanvas = document.createElement('canvas');
this.transitionView = //TODO(zcankara) Instantiate the map panel transition view
new TransitionView(state, this.mapPanel_.transitionView); this.mapPanel_.transitionView = state;
this.isLocked = false; this.isLocked = false;
this._filteredEntries = []; this._filteredEntries = [];
} }
...@@ -169,21 +175,6 @@ class View { ...@@ -169,21 +175,6 @@ class View {
return this.state.map return this.state.map
} }
updateStats() {
this.mapPanel_.timeline = this.state.timeline;
}
updateMapDetails() {
let details = '';
if (this.map) {
details += 'ID: ' + this.map.id;
details += '\nSource location: ' + this.map.filePosition;
details += '\n' + this.map.description;
}
this.mapPanel_.mapDetails.innerText = details;
this.transitionView.showMap(this.map);
}
updateTimeline() { updateTimeline() {
let chunksNode = this.timelinePanel_.timelineChunks; let chunksNode = this.timelinePanel_.timelineChunks;
removeAllChildren(chunksNode); removeAllChildren(chunksNode);
...@@ -218,6 +209,7 @@ class View { ...@@ -218,6 +209,7 @@ class View {
chunk.markers.forEach(marker => addTimestamp(marker.time, marker.name)); chunk.markers.forEach(marker => addTimestamp(marker.time, marker.name));
} }
this.asyncSetTimelineChunkBackground(backgroundTodo) this.asyncSetTimelineChunkBackground(backgroundTodo)
// Put a time marker roughly every 20 chunks. // Put a time marker roughly every 20 chunks.
...@@ -236,6 +228,7 @@ class View { ...@@ -236,6 +228,7 @@ class View {
this.redraw(); this.redraw();
} }
handleChunkMouseMove(event) { handleChunkMouseMove(event) {
if (this.isLocked) return false; if (this.isLocked) return false;
let chunk = event.target.chunk; let chunk = event.target.chunk;
...@@ -255,7 +248,7 @@ class View { ...@@ -255,7 +248,7 @@ class View {
this.isLocked = true; this.isLocked = true;
let chunk = event.target.chunk; let chunk = event.target.chunk;
if (!chunk) return; if (!chunk) return;
this.transitionView.showMaps(chunk.getUniqueTransitions()); this.mapPanel_.showMaps(chunk.getUniqueTransitions());
} }
asyncSetTimelineChunkBackground(backgroundTodo) { asyncSetTimelineChunkBackground(backgroundTodo) {
...@@ -483,139 +476,6 @@ class View { ...@@ -483,139 +476,6 @@ class View {
} }
} }
class TransitionView {
constructor(state, node) {
this.state = state;
this.container = node;
this.currentNode = node;
this.currentMap = undefined;
}
selectMap(map) {
this.currentMap = map;
this.state.map = map;
}
showMap(map) {
if (this.currentMap === map) return;
this.currentMap = map;
this._showMaps([map]);
}
showMaps(list, name) {
this.state.view.isLocked = true;
this._showMaps(list);
}
_showMaps(list, name) {
// Hide the container to avoid any layouts.
this.container.style.display = 'none';
removeAllChildren(this.container);
list.forEach(map => this.addMapAndParentTransitions(map));
this.container.style.display = ''
}
addMapAndParentTransitions(map) {
if (map === void 0) return;
this.currentNode = this.container;
let parents = map.getParents();
if (parents.length > 0) {
this.addTransitionTo(parents.pop());
parents.reverse().forEach(each => this.addTransitionTo(each));
}
let mapNode = this.addSubtransitions(map);
// Mark and show the selected map.
mapNode.classList.add('selected');
if (this.selectedMap == map) {
setTimeout(
() => mapNode.scrollIntoView(
{behavior: 'smooth', block: 'nearest', inline: 'nearest'}),
1);
}
}
addMapNode(map) {
let node = div('map');
if (map.edge) node.style.backgroundColor = map.edge.getColor();
node.map = map;
node.addEventListener('click', () => this.selectMap(map));
if (map.children.length > 1) {
node.innerText = map.children.length;
let showSubtree = div('showSubtransitions');
showSubtree.addEventListener('click', (e) => this.toggleSubtree(e, node));
node.appendChild(showSubtree);
} else if (map.children.length == 0) {
node.innerHTML = '&#x25CF;'
}
this.currentNode.appendChild(node);
return node;
}
addSubtransitions(map) {
let mapNode = this.addTransitionTo(map);
// Draw outgoing linear transition line.
let current = map;
while (current.children.length == 1) {
current = current.children[0].to;
this.addTransitionTo(current);
}
return mapNode;
}
addTransitionEdge(map) {
let classes = ['transitionEdge'];
let edge = div(classes);
edge.style.backgroundColor = map.edge.getColor();
let labelNode = div('transitionLabel');
labelNode.innerText = map.edge.toString();
edge.appendChild(labelNode);
return edge;
}
addTransitionTo(map) {
// transition[ transitions[ transition[...], transition[...], ...]];
let transition = div('transition');
if (map.isDeprecated()) transition.classList.add('deprecated');
if (map.edge) {
transition.appendChild(this.addTransitionEdge(map));
}
let mapNode = this.addMapNode(map);
transition.appendChild(mapNode);
let subtree = div('transitions');
transition.appendChild(subtree);
this.currentNode.appendChild(transition);
this.currentNode = subtree;
return mapNode;
}
toggleSubtree(event, node) {
let map = node.map;
event.target.classList.toggle('opened');
let transitionsNode = node.parentElement.querySelector('.transitions');
let subtransitionNodes = transitionsNode.children;
if (subtransitionNodes.length <= 1) {
// Add subtransitions excepth the one that's already shown.
let visibleTransitionMap = subtransitionNodes.length == 1 ?
transitionsNode.querySelector('.map').map :
void 0;
map.children.forEach(edge => {
if (edge.to != visibleTransitionMap) {
this.currentNode = transitionsNode;
this.addSubtransitions(edge.to);
}
});
} else {
// remove all but the first (currently selected) subtransition
for (let i = subtransitionNodes.length - 1; i > 0; i--) {
transitionsNode.removeChild(subtransitionNodes[i]);
}
}
}
}
// ========================================================================= // =========================================================================
......
...@@ -77,5 +77,174 @@ defineCustomElement('map-panel', (templateText) => ...@@ -77,5 +77,174 @@ defineCustomElement('map-panel', (templateText) =>
'click', {bubbles: true, composed: true, detail: dataModel})); 'click', {bubbles: true, composed: true, detail: dataModel}));
} }
//TODO(zcankara) Take view, transitionView logic inside map panel
//TODO(zcankara) VIEW RELATED
updateStats(timeline) {
this.timeline = timeline;
}
updateMapDetails(map) {
let details = '';
if (map) {
details += 'ID: ' + map.id;
details += '\nSource location: ' + map.filePosition;
details += '\n' + map.description;
}
this.mapDetails.innerText = details;
}
//TODO(zcankara) DOM RELATED
div(classes) {
let node = document.createElement('div');
if (classes !== void 0) {
if (typeof classes === 'string') {
node.classList.add(classes);
} else {
classes.forEach(cls => node.classList.add(cls));
}
}
return node;
}
removeAllChildren(node) {
while (node.lastChild) {
node.removeChild(node.lastChild);
}
}
//TODO(zcankara) TRANSITIONVIEW RELATED
set transitionView(state){
this.state = state;
this.container = this.transitionView;
this.currentNode = this.transitionView;
this.currentMap = undefined;
}
selectMap(map) {
this.currentMap = map;
this.state.map = map;
}
showMap(map) {
this.updateMapDetails(map);
if (this.currentMap === map) return;
this.currentMap = map;
this._showMaps([map]);
}
showMaps(list) {
this.state.view.isLocked = true;
this._showMaps(list);
}
_showMaps(list) {
// Hide the container to avoid any layouts.
this.container.style.display = 'none';
this.removeAllChildren(this.container);
list.forEach(map => this.addMapAndParentTransitions(map));
this.container.style.display = ''
}
addMapAndParentTransitions(map) {
if (map === void 0) return;
this.currentNode = this.container;
let parents = map.getParents();
if (parents.length > 0) {
this.addTransitionTo(parents.pop());
parents.reverse().forEach(each => this.addTransitionTo(each));
}
let mapNode = this.addSubtransitions(map);
// Mark and show the selected map.
mapNode.classList.add('selected');
if (this.selectedMap == map) {
setTimeout(
() => mapNode.scrollIntoView(
{behavior: 'smooth', block: 'nearest', inline: 'nearest'}),
1);
}
}
addMapNode(map) {
let node = this.div('map');
if (map.edge) node.style.backgroundColor = map.edge.getColor();
node.map = map;
node.addEventListener('click', () => this.selectMap(map));
if (map.children.length > 1) {
node.innerText = map.children.length;
let showSubtree = this.div('showSubtransitions');
showSubtree.addEventListener('click', (e) => this.toggleSubtree(e, node));
node.appendChild(showSubtree);
} else if (map.children.length == 0) {
node.innerHTML = '&#x25CF;'
}
this.currentNode.appendChild(node);
return node;
}
addSubtransitions(map) {
let mapNode = this.addTransitionTo(map);
// Draw outgoing linear transition line.
let current = map;
while (current.children.length == 1) {
current = current.children[0].to;
this.addTransitionTo(current);
}
return mapNode;
}
addTransitionEdge(map) {
let classes = ['transitionEdge'];
let edge = this.div(classes);
edge.style.backgroundColor = map.edge.getColor();
let labelNode = this.div('transitionLabel');
labelNode.innerText = map.edge.toString();
edge.appendChild(labelNode);
return edge;
}
addTransitionTo(map) {
// transition[ transitions[ transition[...], transition[...], ...]];
let transition = this.div('transition');
if (map.isDeprecated()) transition.classList.add('deprecated');
if (map.edge) {
transition.appendChild(this.addTransitionEdge(map));
}
let mapNode = this.addMapNode(map);
transition.appendChild(mapNode);
let subtree = this.div('transitions');
transition.appendChild(subtree);
this.currentNode.appendChild(transition);
this.currentNode = subtree;
return mapNode;
}
toggleSubtree(event, node) {
let map = node.map;
event.target.classList.toggle('opened');
let transitionsNode = node.parentElement.querySelector('.transitions');
let subtransitionNodes = transitionsNode.children;
if (subtransitionNodes.length <= 1) {
// Add subtransitions excepth the one that's already shown.
let visibleTransitionMap = subtransitionNodes.length == 1 ?
transitionsNode.querySelector('.map').map :
void 0;
map.children.forEach(edge => {
if (edge.to != visibleTransitionMap) {
this.currentNode = transitionsNode;
this.addSubtransitions(edge.to);
}
});
} else {
// remove all but the first (currently selected) subtransition
for (let i = subtransitionNodes.length - 1; i > 0; i--) {
transitionsNode.removeChild(subtransitionNodes[i]);
}
}
}
}); });
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