11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciimport { PhaseView } from "../src/view";
61cb0ef41Sopenharmony_ciimport { anyToString, ViewElements, isIterable } from "../src/util";
71cb0ef41Sopenharmony_ciimport { MySelection } from "../src/selection";
81cb0ef41Sopenharmony_ciimport { SourceResolver } from "./source-resolver";
91cb0ef41Sopenharmony_ciimport { SelectionBroker } from "./selection-broker";
101cb0ef41Sopenharmony_ciimport { NodeSelectionHandler, BlockSelectionHandler, RegisterAllocationSelectionHandler } from "./selection-handler";
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciexport abstract class TextView extends PhaseView {
131cb0ef41Sopenharmony_ci  selectionHandler: NodeSelectionHandler;
141cb0ef41Sopenharmony_ci  blockSelectionHandler: BlockSelectionHandler;
151cb0ef41Sopenharmony_ci  registerAllocationSelectionHandler: RegisterAllocationSelectionHandler;
161cb0ef41Sopenharmony_ci  selection: MySelection;
171cb0ef41Sopenharmony_ci  blockSelection: MySelection;
181cb0ef41Sopenharmony_ci  registerAllocationSelection: MySelection;
191cb0ef41Sopenharmony_ci  textListNode: HTMLUListElement;
201cb0ef41Sopenharmony_ci  instructionIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
211cb0ef41Sopenharmony_ci  nodeIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
221cb0ef41Sopenharmony_ci  blockIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
231cb0ef41Sopenharmony_ci  blockIdToNodeIds: Map<string, Array<string>>;
241cb0ef41Sopenharmony_ci  nodeIdToBlockId: Array<string>;
251cb0ef41Sopenharmony_ci  patterns: any;
261cb0ef41Sopenharmony_ci  sourceResolver: SourceResolver;
271cb0ef41Sopenharmony_ci  broker: SelectionBroker;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  constructor(id, broker) {
301cb0ef41Sopenharmony_ci    super(id);
311cb0ef41Sopenharmony_ci    const view = this;
321cb0ef41Sopenharmony_ci    view.textListNode = view.divNode.getElementsByTagName('ul')[0];
331cb0ef41Sopenharmony_ci    view.patterns = null;
341cb0ef41Sopenharmony_ci    view.instructionIdToHtmlElementsMap = new Map();
351cb0ef41Sopenharmony_ci    view.nodeIdToHtmlElementsMap = new Map();
361cb0ef41Sopenharmony_ci    view.blockIdToHtmlElementsMap = new Map();
371cb0ef41Sopenharmony_ci    view.blockIdToNodeIds = new Map();
381cb0ef41Sopenharmony_ci    view.nodeIdToBlockId = [];
391cb0ef41Sopenharmony_ci    view.selection = new MySelection(anyToString);
401cb0ef41Sopenharmony_ci    view.blockSelection = new MySelection(anyToString);
411cb0ef41Sopenharmony_ci    view.broker = broker;
421cb0ef41Sopenharmony_ci    view.sourceResolver = broker.sourceResolver;
431cb0ef41Sopenharmony_ci    const selectionHandler = {
441cb0ef41Sopenharmony_ci      clear: function () {
451cb0ef41Sopenharmony_ci        view.selection.clear();
461cb0ef41Sopenharmony_ci        view.updateSelection();
471cb0ef41Sopenharmony_ci        broker.broadcastClear(selectionHandler);
481cb0ef41Sopenharmony_ci      },
491cb0ef41Sopenharmony_ci      select: function (nodeIds, selected) {
501cb0ef41Sopenharmony_ci        view.selection.select(nodeIds, selected);
511cb0ef41Sopenharmony_ci        view.updateSelection();
521cb0ef41Sopenharmony_ci        broker.broadcastNodeSelect(selectionHandler, view.selection.selectedKeys(), selected);
531cb0ef41Sopenharmony_ci      },
541cb0ef41Sopenharmony_ci      brokeredNodeSelect: function (nodeIds, selected) {
551cb0ef41Sopenharmony_ci        const firstSelect = view.blockSelection.isEmpty();
561cb0ef41Sopenharmony_ci        view.selection.select(nodeIds, selected);
571cb0ef41Sopenharmony_ci        view.updateSelection(firstSelect);
581cb0ef41Sopenharmony_ci      },
591cb0ef41Sopenharmony_ci      brokeredClear: function () {
601cb0ef41Sopenharmony_ci        view.selection.clear();
611cb0ef41Sopenharmony_ci        view.updateSelection();
621cb0ef41Sopenharmony_ci      }
631cb0ef41Sopenharmony_ci    };
641cb0ef41Sopenharmony_ci    this.selectionHandler = selectionHandler;
651cb0ef41Sopenharmony_ci    broker.addNodeHandler(selectionHandler);
661cb0ef41Sopenharmony_ci    view.divNode.addEventListener('click', e => {
671cb0ef41Sopenharmony_ci      if (!e.shiftKey) {
681cb0ef41Sopenharmony_ci        view.selectionHandler.clear();
691cb0ef41Sopenharmony_ci      }
701cb0ef41Sopenharmony_ci      e.stopPropagation();
711cb0ef41Sopenharmony_ci    });
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci    const blockSelectionHandler = {
741cb0ef41Sopenharmony_ci      clear: function () {
751cb0ef41Sopenharmony_ci        view.blockSelection.clear();
761cb0ef41Sopenharmony_ci        view.updateSelection();
771cb0ef41Sopenharmony_ci        broker.broadcastClear(blockSelectionHandler);
781cb0ef41Sopenharmony_ci      },
791cb0ef41Sopenharmony_ci      select: function (blockIds, selected) {
801cb0ef41Sopenharmony_ci        view.blockSelection.select(blockIds, selected);
811cb0ef41Sopenharmony_ci        view.updateSelection();
821cb0ef41Sopenharmony_ci        broker.broadcastBlockSelect(blockSelectionHandler, blockIds, selected);
831cb0ef41Sopenharmony_ci      },
841cb0ef41Sopenharmony_ci      brokeredBlockSelect: function (blockIds, selected) {
851cb0ef41Sopenharmony_ci        const firstSelect = view.blockSelection.isEmpty();
861cb0ef41Sopenharmony_ci        view.blockSelection.select(blockIds, selected);
871cb0ef41Sopenharmony_ci        view.updateSelection(firstSelect);
881cb0ef41Sopenharmony_ci      },
891cb0ef41Sopenharmony_ci      brokeredClear: function () {
901cb0ef41Sopenharmony_ci        view.blockSelection.clear();
911cb0ef41Sopenharmony_ci        view.updateSelection();
921cb0ef41Sopenharmony_ci      }
931cb0ef41Sopenharmony_ci    };
941cb0ef41Sopenharmony_ci    this.blockSelectionHandler = blockSelectionHandler;
951cb0ef41Sopenharmony_ci    broker.addBlockHandler(blockSelectionHandler);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci    view.registerAllocationSelection = new MySelection(anyToString);
981cb0ef41Sopenharmony_ci    const registerAllocationSelectionHandler = {
991cb0ef41Sopenharmony_ci      clear: function () {
1001cb0ef41Sopenharmony_ci        view.registerAllocationSelection.clear();
1011cb0ef41Sopenharmony_ci        view.updateSelection();
1021cb0ef41Sopenharmony_ci        broker.broadcastClear(registerAllocationSelectionHandler);
1031cb0ef41Sopenharmony_ci      },
1041cb0ef41Sopenharmony_ci      select: function (instructionIds, selected) {
1051cb0ef41Sopenharmony_ci        view.registerAllocationSelection.select(instructionIds, selected);
1061cb0ef41Sopenharmony_ci        view.updateSelection();
1071cb0ef41Sopenharmony_ci        broker.broadcastInstructionSelect(null, [instructionIds], selected);
1081cb0ef41Sopenharmony_ci      },
1091cb0ef41Sopenharmony_ci      brokeredRegisterAllocationSelect: function (instructionIds, selected) {
1101cb0ef41Sopenharmony_ci        const firstSelect = view.blockSelection.isEmpty();
1111cb0ef41Sopenharmony_ci        view.registerAllocationSelection.select(instructionIds, selected);
1121cb0ef41Sopenharmony_ci        view.updateSelection(firstSelect);
1131cb0ef41Sopenharmony_ci      },
1141cb0ef41Sopenharmony_ci      brokeredClear: function () {
1151cb0ef41Sopenharmony_ci        view.registerAllocationSelection.clear();
1161cb0ef41Sopenharmony_ci        view.updateSelection();
1171cb0ef41Sopenharmony_ci      }
1181cb0ef41Sopenharmony_ci    };
1191cb0ef41Sopenharmony_ci    broker.addRegisterAllocatorHandler(registerAllocationSelectionHandler);
1201cb0ef41Sopenharmony_ci    view.registerAllocationSelectionHandler = registerAllocationSelectionHandler;
1211cb0ef41Sopenharmony_ci  }
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  // instruction-id are the divs for the register allocator phase
1241cb0ef41Sopenharmony_ci  addHtmlElementForInstructionId(anyInstructionId: any, htmlElement: HTMLElement) {
1251cb0ef41Sopenharmony_ci    const instructionId = anyToString(anyInstructionId);
1261cb0ef41Sopenharmony_ci    if (!this.instructionIdToHtmlElementsMap.has(instructionId)) {
1271cb0ef41Sopenharmony_ci      this.instructionIdToHtmlElementsMap.set(instructionId, []);
1281cb0ef41Sopenharmony_ci    }
1291cb0ef41Sopenharmony_ci    this.instructionIdToHtmlElementsMap.get(instructionId).push(htmlElement);
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  addHtmlElementForNodeId(anyNodeId: any, htmlElement: HTMLElement) {
1331cb0ef41Sopenharmony_ci    const nodeId = anyToString(anyNodeId);
1341cb0ef41Sopenharmony_ci    if (!this.nodeIdToHtmlElementsMap.has(nodeId)) {
1351cb0ef41Sopenharmony_ci      this.nodeIdToHtmlElementsMap.set(nodeId, []);
1361cb0ef41Sopenharmony_ci    }
1371cb0ef41Sopenharmony_ci    this.nodeIdToHtmlElementsMap.get(nodeId).push(htmlElement);
1381cb0ef41Sopenharmony_ci  }
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  addHtmlElementForBlockId(anyBlockId, htmlElement) {
1411cb0ef41Sopenharmony_ci    const blockId = anyToString(anyBlockId);
1421cb0ef41Sopenharmony_ci    if (!this.blockIdToHtmlElementsMap.has(blockId)) {
1431cb0ef41Sopenharmony_ci      this.blockIdToHtmlElementsMap.set(blockId, []);
1441cb0ef41Sopenharmony_ci    }
1451cb0ef41Sopenharmony_ci    this.blockIdToHtmlElementsMap.get(blockId).push(htmlElement);
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  addNodeIdToBlockId(anyNodeId, anyBlockId) {
1491cb0ef41Sopenharmony_ci    const blockId = anyToString(anyBlockId);
1501cb0ef41Sopenharmony_ci    if (!this.blockIdToNodeIds.has(blockId)) {
1511cb0ef41Sopenharmony_ci      this.blockIdToNodeIds.set(blockId, []);
1521cb0ef41Sopenharmony_ci    }
1531cb0ef41Sopenharmony_ci    this.blockIdToNodeIds.get(blockId).push(anyToString(anyNodeId));
1541cb0ef41Sopenharmony_ci    this.nodeIdToBlockId[anyNodeId] = blockId;
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  blockIdsForNodeIds(nodeIds) {
1581cb0ef41Sopenharmony_ci    const blockIds = [];
1591cb0ef41Sopenharmony_ci    for (const nodeId of nodeIds) {
1601cb0ef41Sopenharmony_ci      const blockId = this.nodeIdToBlockId[nodeId];
1611cb0ef41Sopenharmony_ci      if (blockId == undefined) continue;
1621cb0ef41Sopenharmony_ci      blockIds.push(blockId);
1631cb0ef41Sopenharmony_ci    }
1641cb0ef41Sopenharmony_ci    return blockIds;
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  updateSelection(scrollIntoView: boolean = false) {
1681cb0ef41Sopenharmony_ci    if (this.divNode.parentNode == null) return;
1691cb0ef41Sopenharmony_ci    const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement);
1701cb0ef41Sopenharmony_ci    const view = this;
1711cb0ef41Sopenharmony_ci    const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`);
1721cb0ef41Sopenharmony_ci    for (const el of elementsToSelect) {
1731cb0ef41Sopenharmony_ci      el.classList.toggle("selected", false);
1741cb0ef41Sopenharmony_ci    }
1751cb0ef41Sopenharmony_ci    for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) {
1761cb0ef41Sopenharmony_ci      const isSelected = view.blockSelection.isSelected(blockId);
1771cb0ef41Sopenharmony_ci      for (const element of elements) {
1781cb0ef41Sopenharmony_ci        mkVisible.consider(element, isSelected);
1791cb0ef41Sopenharmony_ci        element.classList.toggle("selected", isSelected);
1801cb0ef41Sopenharmony_ci      }
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    for (const key of this.instructionIdToHtmlElementsMap.keys()) {
1841cb0ef41Sopenharmony_ci      for (const element of this.instructionIdToHtmlElementsMap.get(key)) {
1851cb0ef41Sopenharmony_ci        element.classList.toggle("selected", false);
1861cb0ef41Sopenharmony_ci      }
1871cb0ef41Sopenharmony_ci    }
1881cb0ef41Sopenharmony_ci    for (const instrId of view.registerAllocationSelection.selectedKeys()) {
1891cb0ef41Sopenharmony_ci      const elements = this.instructionIdToHtmlElementsMap.get(instrId);
1901cb0ef41Sopenharmony_ci      if (!elements) continue;
1911cb0ef41Sopenharmony_ci      for (const element of elements) {
1921cb0ef41Sopenharmony_ci        mkVisible.consider(element, true);
1931cb0ef41Sopenharmony_ci        element.classList.toggle("selected", true);
1941cb0ef41Sopenharmony_ci      }
1951cb0ef41Sopenharmony_ci    }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci    for (const key of this.nodeIdToHtmlElementsMap.keys()) {
1981cb0ef41Sopenharmony_ci      for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
1991cb0ef41Sopenharmony_ci        element.classList.toggle("selected", false);
2001cb0ef41Sopenharmony_ci      }
2011cb0ef41Sopenharmony_ci    }
2021cb0ef41Sopenharmony_ci    for (const nodeId of view.selection.selectedKeys()) {
2031cb0ef41Sopenharmony_ci      const elements = this.nodeIdToHtmlElementsMap.get(nodeId);
2041cb0ef41Sopenharmony_ci      if (!elements) continue;
2051cb0ef41Sopenharmony_ci      for (const element of elements) {
2061cb0ef41Sopenharmony_ci        mkVisible.consider(element, true);
2071cb0ef41Sopenharmony_ci        element.classList.toggle("selected", true);
2081cb0ef41Sopenharmony_ci      }
2091cb0ef41Sopenharmony_ci    }
2101cb0ef41Sopenharmony_ci    mkVisible.apply(scrollIntoView);
2111cb0ef41Sopenharmony_ci  }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  setPatterns(patterns) {
2141cb0ef41Sopenharmony_ci    this.patterns = patterns;
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  clearText() {
2181cb0ef41Sopenharmony_ci    while (this.textListNode.firstChild) {
2191cb0ef41Sopenharmony_ci      this.textListNode.removeChild(this.textListNode.firstChild);
2201cb0ef41Sopenharmony_ci    }
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  createFragment(text, style) {
2241cb0ef41Sopenharmony_ci    const fragment = document.createElement("SPAN");
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci    if (typeof style.associateData == 'function') {
2271cb0ef41Sopenharmony_ci      if (style.associateData(text, fragment) === false) {
2281cb0ef41Sopenharmony_ci         return null;
2291cb0ef41Sopenharmony_ci      }
2301cb0ef41Sopenharmony_ci    } else {
2311cb0ef41Sopenharmony_ci      if (style.css != undefined) {
2321cb0ef41Sopenharmony_ci        const css = isIterable(style.css) ? style.css : [style.css];
2331cb0ef41Sopenharmony_ci        for (const cls of css) {
2341cb0ef41Sopenharmony_ci          fragment.classList.add(cls);
2351cb0ef41Sopenharmony_ci        }
2361cb0ef41Sopenharmony_ci      }
2371cb0ef41Sopenharmony_ci      fragment.innerText = text;
2381cb0ef41Sopenharmony_ci    }
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci    return fragment;
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  processLine(line) {
2441cb0ef41Sopenharmony_ci    const view = this;
2451cb0ef41Sopenharmony_ci    const result = [];
2461cb0ef41Sopenharmony_ci    let patternSet = 0;
2471cb0ef41Sopenharmony_ci    while (true) {
2481cb0ef41Sopenharmony_ci      const beforeLine = line;
2491cb0ef41Sopenharmony_ci      for (const pattern of view.patterns[patternSet]) {
2501cb0ef41Sopenharmony_ci        const matches = line.match(pattern[0]);
2511cb0ef41Sopenharmony_ci        if (matches != null) {
2521cb0ef41Sopenharmony_ci          if (matches[0] != '') {
2531cb0ef41Sopenharmony_ci            const style = pattern[1] != null ? pattern[1] : {};
2541cb0ef41Sopenharmony_ci            const text = matches[0];
2551cb0ef41Sopenharmony_ci            if (text != '') {
2561cb0ef41Sopenharmony_ci              const fragment = view.createFragment(matches[0], style);
2571cb0ef41Sopenharmony_ci              if (fragment !== null) result.push(fragment);
2581cb0ef41Sopenharmony_ci            }
2591cb0ef41Sopenharmony_ci            line = line.substr(matches[0].length);
2601cb0ef41Sopenharmony_ci          }
2611cb0ef41Sopenharmony_ci          let nextPatternSet = patternSet;
2621cb0ef41Sopenharmony_ci          if (pattern.length > 2) {
2631cb0ef41Sopenharmony_ci            nextPatternSet = pattern[2];
2641cb0ef41Sopenharmony_ci          }
2651cb0ef41Sopenharmony_ci          if (line == "") {
2661cb0ef41Sopenharmony_ci            if (nextPatternSet != -1) {
2671cb0ef41Sopenharmony_ci              throw ("illegal parsing state in text-view in patternSet" + patternSet);
2681cb0ef41Sopenharmony_ci            }
2691cb0ef41Sopenharmony_ci            return result;
2701cb0ef41Sopenharmony_ci          }
2711cb0ef41Sopenharmony_ci          patternSet = nextPatternSet;
2721cb0ef41Sopenharmony_ci          break;
2731cb0ef41Sopenharmony_ci        }
2741cb0ef41Sopenharmony_ci      }
2751cb0ef41Sopenharmony_ci      if (beforeLine == line) {
2761cb0ef41Sopenharmony_ci        throw ("input not consumed in text-view in patternSet" + patternSet);
2771cb0ef41Sopenharmony_ci      }
2781cb0ef41Sopenharmony_ci    }
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  processText(text) {
2821cb0ef41Sopenharmony_ci    const view = this;
2831cb0ef41Sopenharmony_ci    const textLines = text.split(/[\n]/);
2841cb0ef41Sopenharmony_ci    let lineNo = 0;
2851cb0ef41Sopenharmony_ci    for (const line of textLines) {
2861cb0ef41Sopenharmony_ci      const li = document.createElement("LI");
2871cb0ef41Sopenharmony_ci      li.className = "nolinenums";
2881cb0ef41Sopenharmony_ci      li.dataset.lineNo = "" + lineNo++;
2891cb0ef41Sopenharmony_ci      const fragments = view.processLine(line);
2901cb0ef41Sopenharmony_ci      for (const fragment of fragments) {
2911cb0ef41Sopenharmony_ci        li.appendChild(fragment);
2921cb0ef41Sopenharmony_ci      }
2931cb0ef41Sopenharmony_ci      view.textListNode.appendChild(li);
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci  }
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  initializeContent(data, rememberedSelection) {
2981cb0ef41Sopenharmony_ci    this.clearText();
2991cb0ef41Sopenharmony_ci    this.processText(data);
3001cb0ef41Sopenharmony_ci    this.show();
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  public onresize(): void {}
3041cb0ef41Sopenharmony_ci}
305