Index: tools/turbolizer/code-view.js |
diff --git a/tools/turbolizer/code-view.js b/tools/turbolizer/code-view.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa106d3ab0f3412e64aded66db9156f61d62feeb |
--- /dev/null |
+++ b/tools/turbolizer/code-view.js |
@@ -0,0 +1,177 @@ |
+// 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. |
+ |
+var CodeView = function(divID, PR, sourceText, sourcePosition, broker) { |
+ "use strict"; |
+ var view = this; |
+ |
+ view.divElement = document.getElementById(divID); |
+ view.broker = broker; |
+ view.codeSelection = null; |
+ view.allSpans = []; |
+ |
+ var selectionHandler = { |
+ clear: function() { |
+ broker.clear(selectionHandler); |
+ }, |
+ select: function(items, selected) { |
+ var handler = this; |
+ var divElement = view.divElement; |
+ var broker = view.broker; |
+ for (let span of items) { |
+ if (selected) { |
+ span.classList.add("selected"); |
+ } else { |
+ span.classList.remove("selected"); |
+ } |
+ } |
+ var ranges = []; |
+ for (var span of items) { |
+ ranges.push([span.start, span.end, null]); |
+ } |
+ broker.select(selectionHandler, ranges, selected); |
+ }, |
+ selectionDifference: function(span1, inclusive1, span2, inclusive2) { |
+ var pos1 = span1.start; |
+ var pos2 = span2.start; |
+ var result = []; |
+ var lineListDiv = view.divElement.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(ranges, selected) { |
+ var firstSelect = view.codeSelection.isEmpty(); |
+ for (var range of ranges) { |
+ var start = range[0]; |
+ var end = range[1]; |
+ var lower = 0; |
+ var 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.divElement, currentLineElement.offsetTop); |
+ firstSelect = false; |
+ } |
+ view.codeSelection.select(currentSpan, selected); |
+ } |
+ } |
+ } |
+ }, |
+ brokeredClear: function() { |
+ view.codeSelection.clear(); |
+ }, |
+ }; |
+ |
+ view.codeSelection = new Selection(selectionHandler); |
+ broker.addSelectionHandler(selectionHandler); |
+ |
+ var mouseDown = false; |
+ |
+ this.handleSpanMouseDown = function(e) { |
+ e.stopPropagation(); |
+ if (!e.shiftKey) { |
+ view.codeSelection.clear(); |
+ } |
+ view.codeSelection.select(this, true); |
+ mouseDown = true; |
+ } |
+ |
+ this.handleSpanMouseMove = function(e) { |
+ if (mouseDown) { |
+ view.codeSelection.extendTo(this); |
+ } |
+ } |
+ |
+ this.handleCodeMouseDown = function(e) { |
+ view.codeSelection.clear(); |
+ } |
+ |
+ document.addEventListener('mouseup', function(e){ |
+ mouseDown = false; |
+ }, false); |
+ |
+ this.initializeCode(sourceText, sourcePosition); |
+} |
+ |
+CodeView.prototype.initializeCode = function(sourceText, sourcePosition) { |
+ var view = this; |
+ if (sourceText == "") { |
+ var newHtml = "<pre class=\"prettyprint\"</pre>"; |
+ view.divElement.innerHTML = newHtml; |
+ } else { |
+ var newHtml = "<pre class=\"prettyprint linenums\">" |
+ + sourceText + "</pre>"; |
+ view.divElement.innerHTML = newHtml; |
+ try { |
+ // Wrap in try to work when offline. |
+ PR.prettyPrint(); |
+ } catch (e) { |
+ } |
+ |
+ view.divElement.onmousedown = this.handleCodeMouseDown; |
+ |
+ var base = sourcePosition; |
+ var current = 0; |
+ var lineListDiv = view.divElement.firstChild.firstChild.childNodes; |
+ for (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 (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; |
+ } |
+ } |
+ } |
+ |
+ this.resizeToParent(); |
+} |
+ |
+CodeView.prototype.resizeToParent = function() { |
+ var view = this; |
+ var documentElement = document.documentElement; |
+ var y = view.divElement.parentNode.clientHeight || documentElement.clientHeight; |
+ view.divElement.style.height = y + "px"; |
+} |