code-view.js 5.63 KB
Newer Older
1 2 3 4
// Copyright 2015 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
"use strict";
6

7 8 9 10 11 12 13 14
class CodeView extends View {
  constructor(divID, PR, sourceText, sourcePosition, broker) {
    super(divID, broker, null, false);
    let view = this;
    view.PR = PR;
    view.mouseDown = false;
    view.broker = broker;
    view.allSpans = [];
15

16 17 18 19 20 21 22 23 24 25
    var selectionHandler = {
      clear: function() { broker.clear(selectionHandler); },
      select: function(items, selected) {
        var handler = this;
        var broker = view.broker;
        for (let span of items) {
          if (selected) {
            span.classList.add("selected");
          } else {
            span.classList.remove("selected");
26 27
          }
        }
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
        var locations = [];
        for (var span of items) {
          locations.push({pos_start: span.start, pos_end: span.end});
        }
        broker.clear(selectionHandler);
        broker.select(selectionHandler, locations, selected);
      },
      selectionDifference: function(span1, inclusive1, span2, inclusive2) {
        var pos1 = span1.start;
        var pos2 = span2.start;
        var result = [];
        var lineListDiv = view.divNode.firstChild.firstChild.childNodes;
        for (var i = 0; i < lineListDiv.length; i++) {
          var currentLineElement = lineListDiv[i];
          var spans = currentLineElement.childNodes;
          for (var j = 0; j < spans.length; ++j) {
            var currentSpan = spans[j];
            if (currentSpan.start > pos1 ||
                (inclusive1 && currentSpan.start == pos1)) {
              if (currentSpan.start < pos2 ||
                  (inclusive2 && currentSpan.start == pos2)) {
                result.push(currentSpan);
              }
51 52
            }
          }
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
        }
        return result;
      },
      brokeredSelect: function(locations, selected) {
        let firstSelect = view.selection.isEmpty();
        for (let location of locations) {
          let start = location.pos_start;
          let end = location.pos_end;
          if (start && end) {
            let lower = 0;
            let upper = view.allSpans.length;
            if (upper > 0) {
              while ((upper - lower) > 1) {
                var middle = Math.floor((upper + lower) / 2);
                var lineStart = view.allSpans[middle].start;
                if (lineStart < start) {
                  lower = middle;
                } else if (lineStart > start) {
                  upper = middle;
                } else {
                  lower = middle;
                  break;
                }
              }
              var currentSpan = view.allSpans[lower];
              var currentLineElement = currentSpan.parentNode;
              if ((currentSpan.start <= start && start < currentSpan.end) ||
                  (currentSpan.start <= end && end < currentSpan.end)) {
                if (firstSelect) {
                  makeContainerPosVisible(
                      view.divNode, currentLineElement.offsetTop);
                  firstSelect = false;
                }
                view.selection.select(currentSpan, selected);
              }
88 89 90
            }
          }
        }
91 92 93 94 95
      },
      brokeredClear: function() { view.selection.clear(); },
    };
    view.selection = new Selection(selectionHandler);
    broker.addSelectionHandler(selectionHandler);
96

97 98 99 100 101 102 103
    view.handleSpanMouseDown = function(e) {
      e.stopPropagation();
      if (!e.shiftKey) {
        view.selection.clear();
      }
      view.selection.select(this, true);
      view.mouseDown = true;
104 105
    }

106 107 108 109
    view.handleSpanMouseMove = function(e) {
      if (view.mouseDown) {
        view.selection.extendTo(this);
      }
110 111
    }

112
    view.handleCodeMouseDown = function(e) { view.selection.clear(); }
113

114 115 116
    document.addEventListener('mouseup', function(e) {
      view.mouseDown = false;
    }, false);
117

118 119
    view.initializeCode(sourceText, sourcePosition);
  }
120

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
  initializeContent(data, rememberedSelection) { this.data = data; }

  initializeCode(sourceText, sourcePosition) {
    var view = this;
    if (sourceText == "") {
      var newHtml = "<pre class=\"prettyprint\"</pre>";
      view.divNode.innerHTML = newHtml;
    } else {
      var newHtml =
          "<pre class=\"prettyprint linenums\">" + sourceText + "</pre>";
      view.divNode.innerHTML = newHtml;
      try {
        // Wrap in try to work when offline.
        view.PR.prettyPrint();
      } catch (e) {
      }
137

138
      view.divNode.onmousedown = this.handleCodeMouseDown;
139

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
      var base = sourcePosition;
      var current = 0;
      var lineListDiv = view.divNode.firstChild.firstChild.childNodes;
      for (let i = 0; i < lineListDiv.length; i++) {
        var currentLineElement = lineListDiv[i];
        currentLineElement.id = "li" + i;
        var pos = base + current;
        currentLineElement.pos = pos;
        var spans = currentLineElement.childNodes;
        for (let j = 0; j < spans.length; ++j) {
          var currentSpan = spans[j];
          if (currentSpan.nodeType == 1) {
            currentSpan.start = pos;
            currentSpan.end = pos + currentSpan.textContent.length;
            currentSpan.onmousedown = this.handleSpanMouseDown;
            currentSpan.onmousemove = this.handleSpanMouseMove;
            view.allSpans.push(currentSpan);
          }
          current += currentSpan.textContent.length;
          pos = base + current;
        }
        while ((current < sourceText.length) &&
               (sourceText[current] == '\n' || sourceText[current] == '\r')) {
          ++current;
164 165 166 167
        }
      }
    }

168 169
    view.resizeToParent();
  }
170

171
  deleteContent() {}
172
}