|
|
|
// 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.
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
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 = [];
|
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
brokeredClear: function() { view.selection.clear(); },
|
|
|
|
};
|
|
|
|
view.selection = new Selection(selectionHandler);
|
|
|
|
broker.addSelectionHandler(selectionHandler);
|
|
|
|
|
|
|
|
view.handleSpanMouseDown = function(e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
if (!e.shiftKey) {
|
|
|
|
view.selection.clear();
|
|
|
|
}
|
|
|
|
view.selection.select(this, true);
|
|
|
|
view.mouseDown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
view.handleSpanMouseMove = function(e) {
|
|
|
|
if (view.mouseDown) {
|
|
|
|
view.selection.extendTo(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
view.handleCodeMouseDown = function(e) { view.selection.clear(); }
|
|
|
|
|
|
|
|
document.addEventListener('mouseup', function(e) {
|
|
|
|
view.mouseDown = false;
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
view.initializeCode(sourceText, sourcePosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
initializeContent(data, rememberedSelection) { this.data = data; }
|
|
|
|
|
|
|
|
initializeCode(sourceText, sourcePosition) {
|
|
|
|
var view = this;
|
|
|
|
var codePre = document.createElement("pre");
|
|
|
|
codePre.classList.add("prettyprint");
|
|
|
|
view.divNode.innerHTML = "";
|
|
|
|
view.divNode.appendChild(codePre);
|
|
|
|
if (sourceText != "") {
|
|
|
|
codePre.classList.add("linenums");
|
|
|
|
codePre.textContent = sourceText;
|
|
|
|
try {
|
|
|
|
// Wrap in try to work when offline.
|
|
|
|
view.PR.prettyPrint();
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
|
|
|
|
view.divNode.onmousedown = this.handleCodeMouseDown;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
view.resizeToParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteContent() {}
|
|
|
|
}
|