graphmultiview.ts 5.22 KB
Newer Older
1 2 3 4
// 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.

5 6 7 8 9 10
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";
11 12

const multiviewID = "multiview";
13

14
const toolboxHTML = `
15
<div class="graph-toolbox">
16 17 18
  <select id="phase-select">
    <option disabled selected>(please open a file)</option>
  </select>
19 20
  <input id="search-input" type="text" title="search nodes for regex" alt="search node for regex" class="search-input"
    placeholder="find with regexp&hellip;">
21
  <label><input id="search-only-visible" type="checkbox" name="instruction-address" alt="Apply search to visible nodes only">only visible</label>
22
</div>`;
23

24
export class GraphMultiView extends View {
25 26 27 28
  sourceResolver: SourceResolver;
  selectionBroker: SelectionBroker;
  graph: GraphView;
  schedule: ScheduleView;
29
  sequence: SequenceView;
30
  selectMenu: HTMLSelectElement;
31
  currentPhaseView: PhaseView;
32

33
  createViewElement() {
34 35
    const pane = document.createElement("div");
    pane.setAttribute("id", multiviewID);
36
    pane.setAttribute("tabindex", "1");
37
    pane.className = "viewpane";
38 39 40
    return pane;
  }

41 42 43 44 45
  hide() {
    this.hideCurrentPhase();
    super.hide();
  }

46 47 48 49 50
  constructor(id, selectionBroker, sourceResolver) {
    super(id);
    const view = this;
    view.sourceResolver = sourceResolver;
    view.selectionBroker = selectionBroker;
51
    const toolbox = document.createElement("div");
52
    toolbox.className = "toolbox-anchor";
53
    toolbox.innerHTML = toolboxHTML;
54 55
    view.divNode.appendChild(toolbox);
    const searchInput = toolbox.querySelector("#search-input") as HTMLInputElement;
56
    const onlyVisibleCheckbox = toolbox.querySelector("#search-only-visible") as HTMLInputElement;
57 58
    searchInput.addEventListener("keyup", e => {
      if (!view.currentPhaseView) return;
59
      view.currentPhaseView.searchInputAction(searchInput, e, onlyVisibleCheckbox.checked);
60
    });
61 62 63 64 65
    view.divNode.addEventListener("keyup", (e: KeyboardEvent) => {
      if (e.keyCode == 191) { // keyCode == '/'
        searchInput.focus();
      }
    });
66
    searchInput.setAttribute("value", window.sessionStorage.getItem("lastSearch") || "");
67 68
    this.graph = new GraphView(this.divNode, selectionBroker, view.displayPhaseByName.bind(this),
      toolbox.querySelector(".graph-toolbox"));
69 70
    this.schedule = new ScheduleView(this.divNode, selectionBroker);
    this.sequence = new SequenceView(this.divNode, selectionBroker);
71
    this.selectMenu = toolbox.querySelector("#phase-select") as HTMLSelectElement;
72 73 74 75
  }

  initializeSelect() {
    const view = this;
76 77
    view.selectMenu.innerHTML = "";
    view.sourceResolver.forEachPhase(phase => {
78
      const optionElement = document.createElement("option");
79 80
      let maxNodeId = "";
      if (phase.type == "graph" && phase.highestNodeId != 0) {
81
        maxNodeId = ` ${phase.highestNodeId}`;
82
      }
83
      optionElement.text = `${phase.name}${maxNodeId}`;
84 85
      view.selectMenu.add(optionElement);
    });
86
    this.selectMenu.onchange = function (this: HTMLSelectElement) {
87 88 89
      const phaseIndex = this.selectedIndex;
      window.sessionStorage.setItem("lastSelectedPhase", phaseIndex.toString());
      view.displayPhase(view.sourceResolver.getPhase(phaseIndex));
90
    };
91 92
  }

93
  show() {
94 95 96
    // Insert before is used so that the display is inserted before the
    // resizer for the RangeView.
    this.container.insertBefore(this.divNode, this.container.firstChild);
97 98 99 100 101 102 103
    this.initializeSelect();
    const lastPhaseIndex = +window.sessionStorage.getItem("lastSelectedPhase");
    const initialPhaseIndex = this.sourceResolver.repairPhaseId(lastPhaseIndex);
    this.selectMenu.selectedIndex = initialPhaseIndex;
    this.displayPhase(this.sourceResolver.getPhase(initialPhaseIndex));
  }

104
  displayPhase(phase, selection?: Set<any>) {
105
    if (phase.type == "graph") {
106
      this.displayPhaseView(this.graph, phase, selection);
107
    } else if (phase.type == "schedule") {
108
      this.displayPhaseView(this.schedule, phase, selection);
109
    } else if (phase.type == "sequence") {
110
      this.displayPhaseView(this.sequence, phase, selection);
111 112 113
    }
  }

114
  displayPhaseView(view: PhaseView, data, selection?: Set<any>) {
115
    const rememberedSelection = selection ? selection : this.hideCurrentPhase();
116
    view.initializeContent(data, rememberedSelection);
117 118 119
    this.currentPhaseView = view;
  }

120
  displayPhaseByName(phaseName, selection?: Set<any>) {
121
    const phaseId = this.sourceResolver.getPhaseIdByName(phaseName);
122 123
    this.selectMenu.selectedIndex = phaseId;
    this.displayPhase(this.sourceResolver.getPhase(phaseId), selection);
124 125 126 127 128 129 130 131 132 133 134 135 136
  }

  hideCurrentPhase() {
    let rememberedSelection = null;
    if (this.currentPhaseView != null) {
      rememberedSelection = this.currentPhaseView.detachSelection();
      this.currentPhaseView.hide();
      this.currentPhaseView = null;
    }
    return rememberedSelection;
  }

  onresize() {
137
    if (this.currentPhaseView) this.currentPhaseView.onresize();
138 139
  }

140 141 142
  detachSelection() {
    return null;
  }
143
}