// Copyright 2018 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 { GraphView } from "../src/graph-view"; import { ScheduleView } from "../src/schedule-view"; import { SequenceView } from "../src/sequence-view"; import { SourceResolver } from "../src/source-resolver"; import { SelectionBroker } from "../src/selection-broker"; import { View, PhaseView } from "../src/view"; const multiviewID = "multiview"; const toolboxHTML = ` <div class="graph-toolbox"> <select id="phase-select"> <option disabled selected>(please open a file)</option> </select> <input id="search-input" type="text" title="search nodes for regex" alt="search node for regex" class="search-input" placeholder="find with regexp…"> <label><input id="search-only-visible" type="checkbox" name="instruction-address" alt="Apply search to visible nodes only">only visible</label> </div>`; export class GraphMultiView extends View { sourceResolver: SourceResolver; selectionBroker: SelectionBroker; graph: GraphView; schedule: ScheduleView; sequence: SequenceView; selectMenu: HTMLSelectElement; currentPhaseView: PhaseView; createViewElement() { const pane = document.createElement("div"); pane.setAttribute("id", multiviewID); pane.className = "viewpane"; return pane; } constructor(id, selectionBroker, sourceResolver) { super(id); const view = this; view.sourceResolver = sourceResolver; view.selectionBroker = selectionBroker; const toolbox = document.createElement("div"); toolbox.className = "toolbox-anchor"; toolbox.innerHTML = toolboxHTML; view.divNode.appendChild(toolbox); const searchInput = toolbox.querySelector("#search-input") as HTMLInputElement; const onlyVisibleCheckbox = toolbox.querySelector("#search-only-visible") as HTMLInputElement; searchInput.addEventListener("keyup", e => { if (!view.currentPhaseView) return; view.currentPhaseView.searchInputAction(searchInput, e, onlyVisibleCheckbox.checked); }); view.divNode.addEventListener("keyup", (e: KeyboardEvent) => { if (e.keyCode == 191) { // keyCode == '/' searchInput.focus(); } }); searchInput.setAttribute("value", window.sessionStorage.getItem("lastSearch") || ""); this.graph = new GraphView(this.divNode, selectionBroker, view.displayPhaseByName.bind(this), toolbox.querySelector(".graph-toolbox")); this.schedule = new ScheduleView(this.divNode, selectionBroker); this.sequence = new SequenceView(this.divNode, selectionBroker); this.selectMenu = toolbox.querySelector("#phase-select") as HTMLSelectElement; } initializeSelect() { const view = this; view.selectMenu.innerHTML = ""; view.sourceResolver.forEachPhase(phase => { const optionElement = document.createElement("option"); let maxNodeId = ""; if (phase.type == "graph" && phase.highestNodeId != 0) { maxNodeId = ` ${phase.highestNodeId}`; } optionElement.text = `${phase.name}${maxNodeId}`; view.selectMenu.add(optionElement); }); this.selectMenu.onchange = function (this: HTMLSelectElement) { const phaseIndex = this.selectedIndex; window.sessionStorage.setItem("lastSelectedPhase", phaseIndex.toString()); view.displayPhase(view.sourceResolver.getPhase(phaseIndex)); }; } show() { super.show(); this.initializeSelect(); const lastPhaseIndex = +window.sessionStorage.getItem("lastSelectedPhase"); const initialPhaseIndex = this.sourceResolver.repairPhaseId(lastPhaseIndex); this.selectMenu.selectedIndex = initialPhaseIndex; this.displayPhase(this.sourceResolver.getPhase(initialPhaseIndex)); } displayPhase(phase, selection?: Set<any>) { if (phase.type == "graph") { this.displayPhaseView(this.graph, phase, selection); } else if (phase.type == "schedule") { this.displayPhaseView(this.schedule, phase, selection); } else if (phase.type == "sequence") { this.displayPhaseView(this.sequence, phase, selection); } } displayPhaseView(view: PhaseView, data, selection?: Set<any>) { const rememberedSelection = selection ? selection : this.hideCurrentPhase(); view.initializeContent(data, rememberedSelection); this.divNode.classList.toggle("scrollable", view.isScrollable()); this.currentPhaseView = view; } displayPhaseByName(phaseName, selection?: Set<any>) { const phaseId = this.sourceResolver.getPhaseIdByName(phaseName); this.selectMenu.selectedIndex = phaseId; this.displayPhase(this.sourceResolver.getPhase(phaseId), selection); } hideCurrentPhase() { let rememberedSelection = null; if (this.currentPhaseView != null) { rememberedSelection = this.currentPhaseView.detachSelection(); this.currentPhaseView.hide(); this.currentPhaseView = null; } return rememberedSelection; } onresize() { if (this.currentPhaseView) this.currentPhaseView.onresize(); } detachSelection() { return null; } }