Merge current ajaxorg:master with jviereck:wrapMode
This commit is contained in:
commit
725820e05d
15 changed files with 937 additions and 358 deletions
|
|
@ -44,7 +44,7 @@ exports.launch = function(env) {
|
||||||
var event = require("pilot/event");
|
var event = require("pilot/event");
|
||||||
var Editor = require("ace/editor").Editor;
|
var Editor = require("ace/editor").Editor;
|
||||||
var Renderer = require("ace/virtual_renderer").VirtualRenderer;
|
var Renderer = require("ace/virtual_renderer").VirtualRenderer;
|
||||||
var theme = require("ace/theme/textmate");
|
var theme = require("ace/theme/textmate");
|
||||||
var EditSession = require("ace/edit_session").EditSession;
|
var EditSession = require("ace/edit_session").EditSession;
|
||||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||||
var CssMode = require("ace/mode/css").Mode;
|
var CssMode = require("ace/mode/css").Mode;
|
||||||
|
|
@ -58,17 +58,27 @@ exports.launch = function(env) {
|
||||||
var vim = require("ace/keyboard/keybinding/vim").Vim;
|
var vim = require("ace/keyboard/keybinding/vim").Vim;
|
||||||
var emacs = require("ace/keyboard/keybinding/emacs").Emacs;
|
var emacs = require("ace/keyboard/keybinding/emacs").Emacs;
|
||||||
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
|
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
|
||||||
|
|
||||||
var docs = {};
|
var docs = {};
|
||||||
|
|
||||||
|
// Make the lorem ipsum text a little bit longer.
|
||||||
|
var loreIpsum = document.getElementById("plaintext").innerHTML;
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
loreIpsum += loreIpsum;
|
||||||
|
}
|
||||||
|
docs.plain = new EditSession(loreIpsum);
|
||||||
|
docs.plain.setUseWrapMode(true);
|
||||||
|
docs.plain.setMode(new TextMode());
|
||||||
|
docs.plain.setUndoManager(new UndoManager());
|
||||||
|
|
||||||
docs.js = new EditSession(document.getElementById("jstext").innerHTML);
|
docs.js = new EditSession(document.getElementById("jstext").innerHTML);
|
||||||
docs.js.setMode(new JavaScriptMode());
|
docs.js.setMode(new JavaScriptMode());
|
||||||
docs.js.setUndoManager(new UndoManager());
|
docs.js.setUndoManager(new UndoManager());
|
||||||
|
|
||||||
if (false && window.Worker) {
|
if (false && window.Worker) {
|
||||||
var worker = new WorkerClient("../..", ["ace", "pilot"], "ace/worker/mirror", "Mirror");
|
var worker = new WorkerClient("../..", ["ace", "pilot"], "ace/worker/mirror", "Mirror");
|
||||||
worker.call("setValue", [docs.js.getValue()]);
|
worker.call("setValue", [docs.js.getValue()]);
|
||||||
|
|
||||||
docs.js.getDocument().on("change", function(e) {
|
docs.js.getDocument().on("change", function(e) {
|
||||||
e.range = {
|
e.range = {
|
||||||
start: e.data.range.start,
|
start: e.data.range.start,
|
||||||
|
|
@ -76,7 +86,7 @@ exports.launch = function(env) {
|
||||||
};
|
};
|
||||||
worker.emit("change", e);
|
worker.emit("change", e);
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.on("jslint", function(results) {
|
worker.on("jslint", function(results) {
|
||||||
var errors = [];
|
var errors = [];
|
||||||
for (var i=0; i<results.data.length; i++) {
|
for (var i=0; i<results.data.length; i++) {
|
||||||
|
|
@ -90,11 +100,11 @@ exports.launch = function(env) {
|
||||||
lint: error
|
lint: error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
docs.js.setAnnotations(errors)
|
docs.js.setAnnotations(errors)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
docs.css = new EditSession(document.getElementById("csstext").innerHTML);
|
docs.css = new EditSession(document.getElementById("csstext").innerHTML);
|
||||||
docs.css.setMode(new CssMode());
|
docs.css.setMode(new CssMode());
|
||||||
docs.css.setUndoManager(new UndoManager());
|
docs.css.setUndoManager(new UndoManager());
|
||||||
|
|
@ -114,7 +124,7 @@ exports.launch = function(env) {
|
||||||
|
|
||||||
var container = document.getElementById("editor");
|
var container = document.getElementById("editor");
|
||||||
env.editor = new Editor(new Renderer(container, theme));
|
env.editor = new Editor(new Renderer(container, theme));
|
||||||
|
|
||||||
var modes = {
|
var modes = {
|
||||||
text: new TextMode(),
|
text: new TextMode(),
|
||||||
xml: new XmlMode(),
|
xml: new XmlMode(),
|
||||||
|
|
@ -129,7 +139,6 @@ exports.launch = function(env) {
|
||||||
return modes[modeEl.value];
|
return modes[modeEl.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var modeEl = document.getElementById("mode");
|
var modeEl = document.getElementById("mode");
|
||||||
function setMode() {
|
function setMode() {
|
||||||
env.editor.getSession().setMode(modes[modeEl.value] || modes.text);
|
env.editor.getSession().setMode(modes[modeEl.value] || modes.text);
|
||||||
|
|
@ -151,7 +160,7 @@ exports.launch = function(env) {
|
||||||
function onDocChange() {
|
function onDocChange() {
|
||||||
var doc = docs[docEl.value];
|
var doc = docs[docEl.value];
|
||||||
env.editor.setSession(doc);
|
env.editor.setSession(doc);
|
||||||
|
|
||||||
var mode = doc.getMode();
|
var mode = doc.getMode();
|
||||||
if (mode instanceof JavaScriptMode) {
|
if (mode instanceof JavaScriptMode) {
|
||||||
modeEl.value = "javascript";
|
modeEl.value = "javascript";
|
||||||
|
|
@ -174,7 +183,7 @@ exports.launch = function(env) {
|
||||||
else {
|
else {
|
||||||
modeEl.value = "text";
|
modeEl.value = "text";
|
||||||
}
|
}
|
||||||
|
|
||||||
env.editor.focus();
|
env.editor.focus();
|
||||||
}
|
}
|
||||||
docEl.onchange = onDocChange;
|
docEl.onchange = onDocChange;
|
||||||
|
|
|
||||||
29
editor.html
29
editor.html
|
|
@ -10,7 +10,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="jump"></div>
|
<div id="jump"></div>
|
||||||
|
|
||||||
<table id="controls">
|
<table id="controls">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
<option value="css">CSS Document</option>
|
<option value="css">CSS Document</option>
|
||||||
<option value="python">Python Document</option>
|
<option value="python">Python Document</option>
|
||||||
<option value="php">PHP Document</option>
|
<option value="php">PHP Document</option>
|
||||||
|
<option value="plain">Text Document</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -48,25 +49,25 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<label for="select_style">Full line selections</label>
|
<label for="select_style">Full line selections</label>
|
||||||
<input type="checkbox" name="select_style" id="select_style" checked>
|
<input type="checkbox" name="select_style" id="select_style" checked>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<label for="highlight_active">Highlight active line</label>
|
<label for="highlight_active">Highlight active line</label>
|
||||||
<input type="checkbox" name="highlight_active" id="highlight_active" checked>
|
<input type="checkbox" name="highlight_active" id="highlight_active" checked>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<label for="show_hidden">Show invisibles</label>
|
<label for="show_hidden">Show invisibles</label>
|
||||||
<input type="checkbox" name="show_hidden" id="show_hidden">
|
<input type="checkbox" name="show_hidden" id="show_hidden">
|
||||||
</td>
|
</td>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<img src="demo/logo.png">
|
<img src="demo/logo.png">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div id="editor">
|
<div id="editor">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/editor" id="jstext">function foo(items) {
|
<script type="text/editor" id="jstext">function foo(items) {
|
||||||
for (var i=0; i<items.length; i++) {
|
for (var i=0; i<items.length; i++) {
|
||||||
alert(items[i] + "juhu");
|
alert(items[i] + "juhu");
|
||||||
|
|
@ -97,7 +98,7 @@
|
||||||
</html></script>
|
</html></script>
|
||||||
|
|
||||||
<script type="text/editor" id="pythontext">#!/usr/local/bin/python
|
<script type="text/editor" id="pythontext">#!/usr/local/bin/python
|
||||||
|
|
||||||
import string, sys
|
import string, sys
|
||||||
|
|
||||||
# If no arguments were given, print a helpful message
|
# If no arguments were given, print a helpful message
|
||||||
|
|
@ -107,7 +108,7 @@ if len(sys.argv)==1:
|
||||||
|
|
||||||
# Loop over the arguments
|
# Loop over the arguments
|
||||||
for i in sys.argv[1:]:
|
for i in sys.argv[1:]:
|
||||||
try:
|
try:
|
||||||
fahrenheit=float(string.atoi(i))
|
fahrenheit=float(string.atoi(i))
|
||||||
except string.atoi_error:
|
except string.atoi_error:
|
||||||
print repr(i), "not a numeric value"
|
print repr(i), "not a numeric value"
|
||||||
|
|
@ -141,5 +142,17 @@ echo $output;
|
||||||
<script src="demo/require.js" type="text/javascript" charset="utf-8"></script>
|
<script src="demo/require.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="demo/boot.js" type="text/javascript"></script>
|
<script src="demo/boot.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script type="text/editor" id="plaintext">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||||
|
|
||||||
|
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||||
|
|
||||||
|
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||||
|
|
||||||
|
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||||
|
|
||||||
|
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
||||||
|
|
||||||
|
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,9 @@ var Document = function(text) {
|
||||||
this.getValue = function() {
|
this.getValue = function() {
|
||||||
return this.$lines.join(this.getNewLineCharacter());
|
return this.$lines.join(this.getNewLineCharacter());
|
||||||
};
|
};
|
||||||
|
|
||||||
// check for IE split bug
|
// check for IE split bug
|
||||||
if ("aaa".split(/a/).length == 0)
|
if ("aaa".split(/a/).length == 0)
|
||||||
this.$split = function(text) {
|
this.$split = function(text) {
|
||||||
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ var Document = function(text) {
|
||||||
return text.split(/\r\n|\r|\n/);
|
return text.split(/\r\n|\r|\n/);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.$detectNewLine = function(text) {
|
this.$detectNewLine = function(text) {
|
||||||
var match = text.match(/^.*?(\r?\n)/m);
|
var match = text.match(/^.*?(\r?\n)/m);
|
||||||
if (match) {
|
if (match) {
|
||||||
|
|
@ -84,7 +84,7 @@ var Document = function(text) {
|
||||||
this.$autoNewLine = "\n";
|
this.$autoNewLine = "\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getNewLineCharacter = function() {
|
this.getNewLineCharacter = function() {
|
||||||
switch (this.$newLineMode) {
|
switch (this.$newLineMode) {
|
||||||
case "windows":
|
case "windows":
|
||||||
|
|
@ -109,24 +109,24 @@ var Document = function(text) {
|
||||||
this.getNewLineMode = function() {
|
this.getNewLineMode = function() {
|
||||||
return this.$newLineMode;
|
return this.$newLineMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isNewLine = function(text) {
|
this.isNewLine = function(text) {
|
||||||
return (text == "\r\n" || text == "\r" || text == "\n");
|
return (text == "\r\n" || text == "\r" || text == "\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a verbatim copy of the given line as it is in the document
|
* Get a verbatim copy of the given line as it is in the document
|
||||||
*/
|
*/
|
||||||
this.getLine = function(row) {
|
this.getLine = function(row) {
|
||||||
return this.$lines[row] || "";
|
return this.$lines[row] || "";
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getLines = function(firstRow, lastRow) {
|
this.getLines = function(firstRow, lastRow) {
|
||||||
return this.$lines.slice(firstRow, lastRow+1);
|
return this.$lines.slice(firstRow, lastRow+1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all lines in the document as string array. Warning: The caller
|
* Returns all lines in the document as string array. Warning: The caller
|
||||||
* should not modify this array!
|
* should not modify this array!
|
||||||
*/
|
*/
|
||||||
this.getAllLines = function() {
|
this.getAllLines = function() {
|
||||||
|
|
@ -157,15 +157,15 @@ var Document = function(text) {
|
||||||
position.row = Math.max(0, length - 1);
|
position.row = Math.max(0, length - 1);
|
||||||
position.column = this.getLine(length-1).length;
|
position.column = this.getLine(length-1).length;
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.insert = function(position, text) {
|
this.insert = function(position, text) {
|
||||||
if (text.length == 0)
|
if (text.length == 0)
|
||||||
return position;
|
return position;
|
||||||
|
|
||||||
position = this.$clipPosition(position);
|
position = this.$clipPosition(position);
|
||||||
|
|
||||||
if (this.getLength() <= 1)
|
if (this.getLength() <= 1)
|
||||||
this.$detectNewLine(text);
|
this.$detectNewLine(text);
|
||||||
|
|
||||||
|
|
@ -182,56 +182,56 @@ var Document = function(text) {
|
||||||
this.insertNewLine(end);
|
this.insertNewLine(end);
|
||||||
if (newLines.length > 2)
|
if (newLines.length > 2)
|
||||||
this.insertLines(position.row+1, newLines.slice(1, newLines.length-1));
|
this.insertLines(position.row+1, newLines.slice(1, newLines.length-1));
|
||||||
|
|
||||||
var end = this.insertInLine({row: position.row + newLines.length - 1, column: 0}, newLines[newLines.length-1]);
|
var end = this.insertInLine({row: position.row + newLines.length - 1, column: 0}, newLines[newLines.length-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.insertLines = function(row, lines) {
|
this.insertLines = function(row, lines) {
|
||||||
if (lines.length == 0)
|
if (lines.length == 0)
|
||||||
return {row: row, column: 0};
|
return {row: row, column: 0};
|
||||||
|
|
||||||
var args = [row, 0];
|
var args = [row, 0];
|
||||||
args.push.apply(args, lines);
|
args.push.apply(args, lines);
|
||||||
this.$lines.splice.apply(this.$lines, args);
|
this.$lines.splice.apply(this.$lines, args);
|
||||||
|
|
||||||
var range = new Range(row, 0, row + lines.length - 1, 0);
|
var range = new Range(row, 0, row + lines.length - 1, 0);
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "insertLines",
|
action: "insertLines",
|
||||||
range: range,
|
range: range,
|
||||||
lines: lines
|
lines: lines
|
||||||
};
|
};
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
return range.end;
|
return range.end;
|
||||||
},
|
},
|
||||||
|
|
||||||
this.insertNewLine = function(position) {
|
this.insertNewLine = function(position) {
|
||||||
position = this.$clipPosition(position);
|
position = this.$clipPosition(position);
|
||||||
var line = this.$lines[position.row] || "";
|
var line = this.$lines[position.row] || "";
|
||||||
this.$lines[position.row] = line.substring(0, position.column);
|
this.$lines[position.row] = line.substring(0, position.column);
|
||||||
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
|
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
|
||||||
|
|
||||||
var end = {
|
var end = {
|
||||||
row : position.row + 1,
|
row : position.row + 1,
|
||||||
column : 0
|
column : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "insertText",
|
action: "insertText",
|
||||||
range: Range.fromPoints(position, end),
|
range: Range.fromPoints(position, end),
|
||||||
text: this.getNewLineCharacter()
|
text: this.getNewLineCharacter()
|
||||||
};
|
};
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.insertInLine = function(position, text) {
|
this.insertInLine = function(position, text) {
|
||||||
if (text.length == 0)
|
if (text.length == 0)
|
||||||
return position;
|
return position;
|
||||||
|
|
||||||
var line = this.$lines[position.row] || "";
|
var line = this.$lines[position.row] || "";
|
||||||
this.$lines[position.row] = line.substring(0, position.column) + text
|
this.$lines[position.row] = line.substring(0, position.column) + text
|
||||||
+ line.substring(position.column);
|
+ line.substring(position.column);
|
||||||
|
|
@ -240,14 +240,14 @@ var Document = function(text) {
|
||||||
row : position.row,
|
row : position.row,
|
||||||
column : position.column + text.length
|
column : position.column + text.length
|
||||||
};
|
};
|
||||||
|
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "insertText",
|
action: "insertText",
|
||||||
range: Range.fromPoints(position, end),
|
range: Range.fromPoints(position, end),
|
||||||
text: text
|
text: text
|
||||||
};
|
};
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -258,12 +258,12 @@ var Document = function(text) {
|
||||||
|
|
||||||
if (range.isEmpty())
|
if (range.isEmpty())
|
||||||
return range.start;
|
return range.start;
|
||||||
|
|
||||||
var firstRow = range.start.row;
|
var firstRow = range.start.row;
|
||||||
var lastRow = range.end.row;
|
var lastRow = range.end.row;
|
||||||
|
|
||||||
if (range.isMultiLine()) {
|
if (range.isMultiLine()) {
|
||||||
|
|
||||||
// TODO removeInLine can be optimized away!
|
// TODO removeInLine can be optimized away!
|
||||||
this.removeInLine(lastRow, 0, range.end.column);
|
this.removeInLine(lastRow, 0, range.end.column);
|
||||||
if (lastRow - firstRow >= 2)
|
if (lastRow - firstRow >= 2)
|
||||||
|
|
@ -276,17 +276,17 @@ var Document = function(text) {
|
||||||
}
|
}
|
||||||
return range.start;
|
return range.start;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeInLine = function(row, startColumn, endColumn) {
|
this.removeInLine = function(row, startColumn, endColumn) {
|
||||||
if (startColumn == endColumn)
|
if (startColumn == endColumn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var range = new Range(row, startColumn, row, endColumn);
|
var range = new Range(row, startColumn, row, endColumn);
|
||||||
var line = this.getLine(row);
|
var line = this.getLine(row);
|
||||||
var removed = line.substring(startColumn, endColumn);
|
var removed = line.substring(startColumn, endColumn);
|
||||||
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
||||||
this.$lines.splice(row, 1, newLine);
|
this.$lines.splice(row, 1, newLine);
|
||||||
|
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "removeText",
|
action: "removeText",
|
||||||
range: range,
|
range: range,
|
||||||
|
|
@ -295,18 +295,18 @@ var Document = function(text) {
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
return range.start;
|
return range.start;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a range of full lines
|
* Removes a range of full lines
|
||||||
*
|
*
|
||||||
* @param firstRow {Integer} The first row to be removed
|
* @param firstRow {Integer} The first row to be removed
|
||||||
* @param lastRow {Integer} The last row to be removed
|
* @param lastRow {Integer} The last row to be removed
|
||||||
* @return {String[]} The removed lines
|
* @return {String[]} The removed lines
|
||||||
*/
|
*/
|
||||||
this.removeLines = function(firstRow, lastRow) {
|
this.removeLines = function(firstRow, lastRow) {
|
||||||
var range = new Range(firstRow, 0, lastRow, this.$lines[lastRow].length);
|
var range = new Range(firstRow, 0, lastRow, this.$lines[lastRow].length);
|
||||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||||
|
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "removeLines",
|
action: "removeLines",
|
||||||
range: range,
|
range: range,
|
||||||
|
|
@ -316,16 +316,16 @@ var Document = function(text) {
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
return removed;
|
return removed;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeNewLine = function(row) {
|
this.removeNewLine = function(row) {
|
||||||
var firstLine = this.getLine(row);
|
var firstLine = this.getLine(row);
|
||||||
var secondLine = this.getLine(row+1);
|
var secondLine = this.getLine(row+1);
|
||||||
|
|
||||||
var range = new Range(row, firstLine.length, row+1, 0);
|
var range = new Range(row, firstLine.length, row+1, 0);
|
||||||
var line = firstLine + secondLine;
|
var line = firstLine + secondLine;
|
||||||
|
|
||||||
this.$lines.splice(row, 2, line);
|
this.$lines.splice(row, 2, line);
|
||||||
|
|
||||||
var delta = {
|
var delta = {
|
||||||
action: "removeText",
|
action: "removeText",
|
||||||
range: range,
|
range: range,
|
||||||
|
|
@ -333,16 +333,16 @@ var Document = function(text) {
|
||||||
};
|
};
|
||||||
this._dispatchEvent("change", { data: delta });
|
this._dispatchEvent("change", { data: delta });
|
||||||
};
|
};
|
||||||
|
|
||||||
this.replace = function(range, text) {
|
this.replace = function(range, text) {
|
||||||
if (text.length == 0 && range.isEmpty())
|
if (text.length == 0 && range.isEmpty())
|
||||||
return range.start;
|
return range.start;
|
||||||
|
|
||||||
// Shortcut: If the text we want to insert is the same as it is already
|
// Shortcut: If the text we want to insert is the same as it is already
|
||||||
// in the document, we don't have to replace anything.
|
// in the document, we don't have to replace anything.
|
||||||
if (text == this.getTextRange(range))
|
if (text == this.getTextRange(range))
|
||||||
return range.end;
|
return range.end;
|
||||||
|
|
||||||
this.remove(range);
|
this.remove(range);
|
||||||
if (text) {
|
if (text) {
|
||||||
var end = this.insert(range.start, text);
|
var end = this.insert(range.start, text);
|
||||||
|
|
@ -350,15 +350,15 @@ var Document = function(text) {
|
||||||
else {
|
else {
|
||||||
end = range.start;
|
end = range.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.applyDeltas = function(deltas) {
|
this.applyDeltas = function(deltas) {
|
||||||
for (var i=0; i<deltas.length; i++) {
|
for (var i=0; i<deltas.length; i++) {
|
||||||
var delta = deltas[i];
|
var delta = deltas[i];
|
||||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||||
|
|
||||||
if (delta.action == "insertLines")
|
if (delta.action == "insertLines")
|
||||||
this.insertLines(range.start.row, delta.lines)
|
this.insertLines(range.start.row, delta.lines)
|
||||||
else if (delta.action == "insertText")
|
else if (delta.action == "insertText")
|
||||||
|
|
@ -367,14 +367,14 @@ var Document = function(text) {
|
||||||
this.removeLines(range.start.row, range.end.row)
|
this.removeLines(range.start.row, range.end.row)
|
||||||
else if (delta.action == "removeText")
|
else if (delta.action == "removeText")
|
||||||
this.remove(range)
|
this.remove(range)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.revertDeltas = function(deltas) {
|
this.revertDeltas = function(deltas) {
|
||||||
for (var i=deltas.length-1; i>=0; i--) {
|
for (var i=deltas.length-1; i>=0; i--) {
|
||||||
var delta = deltas[i];
|
var delta = deltas[i];
|
||||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||||
|
|
||||||
if (delta.action == "insertLines")
|
if (delta.action == "insertLines")
|
||||||
this.removeLines(range.start.row, range.end.row)
|
this.removeLines(range.start.row, range.end.row)
|
||||||
else if (delta.action == "insertText")
|
else if (delta.action == "insertText")
|
||||||
|
|
@ -383,7 +383,7 @@ var Document = function(text) {
|
||||||
this.insertLines(range.start.row, delta.lines)
|
this.insertLines(range.start.row, delta.lines)
|
||||||
else if (delta.action == "removeText")
|
else if (delta.action == "removeText")
|
||||||
this.insert(range.start, delta.text)
|
this.insert(range.start, delta.text)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(Document.prototype);
|
}).call(Document.prototype);
|
||||||
|
|
|
||||||
|
|
@ -51,13 +51,14 @@ var EditSession = function(text, mode) {
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
this.selection = new Selection(this);
|
this.selection = new Selection(this);
|
||||||
this.$breakpoints = [];
|
this.$breakpoints = [];
|
||||||
|
this.$wrapData = [];
|
||||||
|
|
||||||
if (text instanceof Document) {
|
if (text instanceof Document) {
|
||||||
this.setDocument(text)
|
this.setDocument(text)
|
||||||
} else {
|
} else {
|
||||||
this.setDocument(new Document(text));
|
this.setDocument(new Document(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode)
|
if (mode)
|
||||||
this.setMode(mode);
|
this.setMode(mode);
|
||||||
};
|
};
|
||||||
|
|
@ -70,15 +71,15 @@ var EditSession = function(text, mode) {
|
||||||
this.setDocument = function(doc) {
|
this.setDocument = function(doc) {
|
||||||
if (this.doc)
|
if (this.doc)
|
||||||
throw new Error("Document is already set");
|
throw new Error("Document is already set");
|
||||||
|
|
||||||
this.doc = doc;
|
this.doc = doc;
|
||||||
doc.on("change", this.onChange.bind(this));
|
doc.on("change", this.onChange.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getDocument = function() {
|
this.getDocument = function() {
|
||||||
return this.doc;
|
return this.doc;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onChange = function(e) {
|
this.onChange = function(e) {
|
||||||
var delta = e.data;
|
var delta = e.data;
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
|
|
@ -86,6 +87,8 @@ var EditSession = function(text, mode) {
|
||||||
this.$deltas.push(delta);
|
this.$deltas.push(delta);
|
||||||
this.$informUndoManager.schedule();
|
this.$informUndoManager.schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$updateWrapDataOnChange(e);
|
||||||
this._dispatchEvent("change", e);
|
this._dispatchEvent("change", e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,7 +101,7 @@ var EditSession = function(text, mode) {
|
||||||
this.toString = function() {
|
this.toString = function() {
|
||||||
return this.doc.getValue();
|
return this.doc.getValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getSelection = function() {
|
this.getSelection = function() {
|
||||||
return this.selection;
|
return this.selection;
|
||||||
};
|
};
|
||||||
|
|
@ -164,7 +167,7 @@ var EditSession = function(text, mode) {
|
||||||
this.getTabSize = function() {
|
this.getTabSize = function() {
|
||||||
return this.$tabSize;
|
return this.$tabSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isTabStop = function(position) {
|
this.isTabStop = function(position) {
|
||||||
return this.$useSoftTabs && (position.column % this.$tabSize == 0);
|
return this.$useSoftTabs && (position.column % this.$tabSize == 0);
|
||||||
};
|
};
|
||||||
|
|
@ -201,7 +204,7 @@ var EditSession = function(text, mode) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error:
|
* Error:
|
||||||
* {
|
* {
|
||||||
* row: 12,
|
* row: 12,
|
||||||
* column: 2, //can be undefined
|
* column: 2, //can be undefined
|
||||||
|
|
@ -225,7 +228,7 @@ var EditSession = function(text, mode) {
|
||||||
this.getAnnotations = function() {
|
this.getAnnotations = function() {
|
||||||
return this.$annotations;
|
return this.$annotations;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clearAnnotations = function() {
|
this.clearAnnotations = function() {
|
||||||
this.$annotations = [];
|
this.$annotations = [];
|
||||||
this._dispatchEvent("changeAnnotation", {});
|
this._dispatchEvent("changeAnnotation", {});
|
||||||
|
|
@ -239,12 +242,12 @@ var EditSession = function(text, mode) {
|
||||||
this.$autoNewLine = "\n";
|
this.$autoNewLine = "\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.tokenRe = /^[\w\d]+/g;
|
this.tokenRe = /^[\w\d]+/g;
|
||||||
this.nonTokenRe = /^(?:[^\w\d|[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF])+/g
|
this.nonTokenRe = /^(?:[^\w\d|[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF])+/g
|
||||||
this.getWordRange = function(row, column) {
|
this.getWordRange = function(row, column) {
|
||||||
var line = this.getLine(row);
|
var line = this.getLine(row);
|
||||||
|
|
||||||
var inToken = false;
|
var inToken = false;
|
||||||
if (column > 0) {
|
if (column > 0) {
|
||||||
inToken = !!line.charAt(column - 1).match(this.tokenRe);
|
inToken = !!line.charAt(column - 1).match(this.tokenRe);
|
||||||
|
|
@ -287,7 +290,7 @@ var EditSession = function(text, mode) {
|
||||||
|
|
||||||
if (this.$worker)
|
if (this.$worker)
|
||||||
this.$worker.terminate();
|
this.$worker.terminate();
|
||||||
|
|
||||||
if (window.Worker)
|
if (window.Worker)
|
||||||
this.$worker = mode.createWorker(this);
|
this.$worker = mode.createWorker(this);
|
||||||
|
|
||||||
|
|
@ -315,18 +318,18 @@ var EditSession = function(text, mode) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getWidth = function() {
|
this.getWidth = function() {
|
||||||
this.$computeWidth();
|
this.$computeWidth(!this.width);
|
||||||
return this.width;
|
return this.width;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getScreenWidth = function() {
|
this.getScreenWidth = function() {
|
||||||
this.$computeWidth();
|
this.$computeWidth(!this.screenWidth);
|
||||||
return this.screenWidth;
|
return this.screenWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$computeWidth = function() {
|
this.$computeWidth = function(force) {
|
||||||
if (this.$modified) {
|
if (this.modified || force) {
|
||||||
this.$modified = false;
|
this.modified = false;
|
||||||
|
|
||||||
var lines = this.doc.getAllLines();
|
var lines = this.doc.getAllLines();
|
||||||
var longestLine = 0;
|
var longestLine = 0;
|
||||||
|
|
@ -337,24 +340,29 @@ var EditSession = function(text, mode) {
|
||||||
var len = lines[i].length;
|
var len = lines[i].length;
|
||||||
longestLine = Math.max(longestLine, len);
|
longestLine = Math.max(longestLine, len);
|
||||||
|
|
||||||
lines[i].replace(/\t/g, function(m) {
|
lines[i].replace("\t", function(m) {
|
||||||
len += tabSize-1;
|
len += tabSize-1;
|
||||||
return m;
|
return m;
|
||||||
});
|
});
|
||||||
longestScreenLine = Math.max(longestScreenLine, len);
|
longestScreenLine = Math.max(longestScreenLine, len);
|
||||||
}
|
}
|
||||||
this.width = longestLine;
|
this.width = longestLine;
|
||||||
this.screenWidth = longestScreenLine;
|
|
||||||
|
if (this.$useWrapMode) {
|
||||||
|
this.screenWidth = this.$wrapLimit;
|
||||||
|
} else {
|
||||||
|
this.screenWidth = longestScreenLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a verbatim copy of the given line as it is in the document
|
* Get a verbatim copy of the given line as it is in the document
|
||||||
*/
|
*/
|
||||||
this.getLine = function(row) {
|
this.getLine = function(row) {
|
||||||
return this.doc.getLine(row);
|
return this.doc.getLine(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a line as it is displayed on screen. Tabs are replaced by spaces.
|
* Get a line as it is displayed on screen. Tabs are replaced by spaces.
|
||||||
*/
|
*/
|
||||||
|
|
@ -470,16 +478,16 @@ var EditSession = function(text, mode) {
|
||||||
this.insert = function(position, text) {
|
this.insert = function(position, text) {
|
||||||
return this.doc.insert(position, text);
|
return this.doc.insert(position, text);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rows Array[Integer] sorted list of rows
|
* @param rows Array[Integer] sorted list of rows
|
||||||
*/
|
*/
|
||||||
this.multiRowInsert = function(rows, column, text) {
|
this.multiRowInsert = function(rows, column, text) {
|
||||||
for (var i=rows.length-1; i>=0; i--) {
|
for (var i=rows.length-1; i>=0; i--) {
|
||||||
var row = rows[i];
|
var row = rows[i];
|
||||||
if (row >= this.doc.getLength())
|
if (row >= this.doc.getLength())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var diff = column - this.doc.getLine(row).length;
|
var diff = column - this.doc.getLine(row).length;
|
||||||
if ( diff > 0) {
|
if ( diff > 0) {
|
||||||
var padded = lang.stringRepeat(" ", diff) + text;
|
var padded = lang.stringRepeat(" ", diff) + text;
|
||||||
|
|
@ -489,10 +497,10 @@ var EditSession = function(text, mode) {
|
||||||
padded = text;
|
padded = text;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var end = this.insert({row: row, column: column+offset}, padded);
|
var end = this.insert({row: row, column: column+offset}, padded);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rows: end ? end.row - rows[0] : 0,
|
rows: end ? end.row - rows[0] : 0,
|
||||||
columns: end ? end.column - column : 0
|
columns: end ? end.column - column : 0
|
||||||
|
|
@ -506,29 +514,29 @@ var EditSession = function(text, mode) {
|
||||||
this.multiRowRemove = function(rows, range) {
|
this.multiRowRemove = function(rows, range) {
|
||||||
if (range.start.row !== rows[0])
|
if (range.start.row !== rows[0])
|
||||||
throw new TypeError("range must start in the first row!");
|
throw new TypeError("range must start in the first row!");
|
||||||
|
|
||||||
var height = range.end.row - rows[0];
|
var height = range.end.row - rows[0];
|
||||||
for (var i=rows.length-1; i>=0; i--) {
|
for (var i=rows.length-1; i>=0; i--) {
|
||||||
var row = rows[i];
|
var row = rows[i];
|
||||||
if (row >= this.doc.getLength())
|
if (row >= this.doc.getLength())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var end = this.remove(new Range(row, range.start.column, row+height, range.end.column));
|
var end = this.remove(new Range(row, range.start.column, row+height, range.end.column));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.undoChanges = function(deltas) {
|
this.undoChanges = function(deltas) {
|
||||||
if (!deltas.length)
|
if (!deltas.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.$fromUndo = true;
|
this.$fromUndo = true;
|
||||||
this.doc.revertDeltas(deltas);
|
this.doc.revertDeltas(deltas);
|
||||||
this.$fromUndo = false;
|
this.$fromUndo = false;
|
||||||
|
|
||||||
// update the selection
|
// update the selection
|
||||||
var firstDelta = deltas[0];
|
var firstDelta = deltas[0];
|
||||||
var lastDelta = deltas[deltas.length-1];
|
var lastDelta = deltas[deltas.length-1];
|
||||||
|
|
||||||
this.selection.clearSelection();
|
this.selection.clearSelection();
|
||||||
if (firstDelta.action == "insertText" || firstDelta.action == "insertLines")
|
if (firstDelta.action == "insertText" || firstDelta.action == "insertLines")
|
||||||
this.selection.moveCursorToPosition(firstDelta.range.start);
|
this.selection.moveCursorToPosition(firstDelta.range.start);
|
||||||
|
|
@ -539,15 +547,15 @@ var EditSession = function(text, mode) {
|
||||||
this.redoChanges = function(deltas) {
|
this.redoChanges = function(deltas) {
|
||||||
if (!deltas.length)
|
if (!deltas.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.$fromUndo = true;
|
this.$fromUndo = true;
|
||||||
this.doc.applyDeltas(deltas);
|
this.doc.applyDeltas(deltas);
|
||||||
this.$fromUndo = false;
|
this.$fromUndo = false;
|
||||||
|
|
||||||
// update the selection
|
// update the selection
|
||||||
var firstDelta = deltas[0];
|
var firstDelta = deltas[0];
|
||||||
var lastDelta = deltas[deltas.length-1];
|
var lastDelta = deltas[deltas.length-1];
|
||||||
|
|
||||||
this.selection.clearSelection();
|
this.selection.clearSelection();
|
||||||
if (firstDelta.action == "insertText" || firstDelta.action == "insertLines")
|
if (firstDelta.action == "insertText" || firstDelta.action == "insertLines")
|
||||||
this.selection.setSelectionRange(Range.fromPoints(firstDelta.range.start, lastDelta.range.end));
|
this.selection.setSelectionRange(Range.fromPoints(firstDelta.range.start, lastDelta.range.end));
|
||||||
|
|
@ -571,15 +579,15 @@ var EditSession = function(text, mode) {
|
||||||
var rowRange = range.collapseRows();
|
var rowRange = range.collapseRows();
|
||||||
var deleteRange = new Range(0, 0, 0, 0);
|
var deleteRange = new Range(0, 0, 0, 0);
|
||||||
var size = this.getTabSize();
|
var size = this.getTabSize();
|
||||||
|
|
||||||
for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
|
for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
|
||||||
var line = this.getLine(i);
|
var line = this.getLine(i);
|
||||||
|
|
||||||
deleteRange.start.row = i;
|
deleteRange.start.row = i;
|
||||||
deleteRange.end.row = i;
|
deleteRange.end.row = i;
|
||||||
for (var j = 0; j < size; ++j)
|
for (var j = 0; j < size; ++j)
|
||||||
if (line.charAt(j) != ' ')
|
if (line.charAt(j) != ' ')
|
||||||
break;
|
break;
|
||||||
if (j < size && line.charAt(j) == '\t') {
|
if (j < size && line.charAt(j) == '\t') {
|
||||||
deleteRange.start.column = j;
|
deleteRange.start.column = j;
|
||||||
deleteRange.end.column = j + 1;
|
deleteRange.end.column = j + 1;
|
||||||
|
|
@ -594,7 +602,7 @@ var EditSession = function(text, mode) {
|
||||||
this.remove(deleteRange);
|
this.remove(deleteRange);
|
||||||
}
|
}
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.moveLinesUp = function(firstRow, lastRow) {
|
this.moveLinesUp = function(firstRow, lastRow) {
|
||||||
if (firstRow <= 0) return 0;
|
if (firstRow <= 0) return 0;
|
||||||
|
|
@ -627,15 +635,228 @@ var EditSession = function(text, mode) {
|
||||||
return Math.max(0, Math.min(row, this.doc.getLength()-1));
|
return Math.max(0, Math.min(row, this.doc.getLength()-1));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.documentToScreenColumn = function(row, docColumn) {
|
// WRAPMODE
|
||||||
|
this.$wrapLimit = 80;
|
||||||
|
this.$useWrapMode = false;
|
||||||
|
|
||||||
|
this.setUseWrapMode = function(useWrapMode) {
|
||||||
|
if (useWrapMode != this.$useWrapMode) {
|
||||||
|
this.$useWrapMode = useWrapMode;
|
||||||
|
this.$updateWrapData(0, this.getLength() - 1);
|
||||||
|
this._dispatchEvent("changeWrapMode");
|
||||||
|
// TODO: Add this one back.
|
||||||
|
// this.fireChangeEvent(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getUseWrapMode = function() {
|
||||||
|
return this.$useWrapMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setWrapLimit = function(wrapLimit) {
|
||||||
|
if (wrapLimit != this.$wrapLimit) {
|
||||||
|
this.$wrapLimit = wrapLimit;
|
||||||
|
this.$updateWrapData(0, this.getLength() - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getWrapLimit = function() {
|
||||||
|
return this.$wrapLimit;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$updateWrapDataOnChange = function(e) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var action = e.data.action;
|
||||||
|
var firstRow = e.data.range.start.row,
|
||||||
|
lastRow = e.data.range.end.row;
|
||||||
|
|
||||||
|
if (action.indexOf("Lines") != -1) {
|
||||||
|
if (action == "insertLines") {
|
||||||
|
lastRow = firstRow + e.data.lines.length;
|
||||||
|
} else {
|
||||||
|
firstRow = lastRow - e.data.lines.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstRow != lastRow) {
|
||||||
|
var len = lastRow - firstRow;
|
||||||
|
if (action.indexOf("remove") != -1) {
|
||||||
|
this.$wrapData.splice(firstRow, len);
|
||||||
|
lastRow = firstRow;
|
||||||
|
} else {
|
||||||
|
var args = [firstRow, 0];
|
||||||
|
for (var i = 0; i < len; i++) args.push([]);
|
||||||
|
this.$wrapData.splice.apply(this.$wrapData, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$updateWrapData(firstRow, lastRow);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$updateWrapData = function(firstRow, lastRow) {
|
||||||
|
var lines = this.doc.getAllLines();
|
||||||
var tabSize = this.getTabSize();
|
var tabSize = this.getTabSize();
|
||||||
|
var wrapData = this.$wrapData;
|
||||||
|
var wrapLimit = this.$wrapLimit;
|
||||||
|
|
||||||
|
// Remove lines that are no longer there.
|
||||||
|
wrapData.splice(lines.length, wrapData.length - lines.length);
|
||||||
|
|
||||||
|
for (var row = firstRow; row <= lastRow; row++) {
|
||||||
|
wrapData[row] =
|
||||||
|
this.$computeWrapSplits(lines[row], wrapLimit, tabSize);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$computeWrapSplits = function(textLine, wrapLimit, tabSize) {
|
||||||
|
textLine = textLine.trimRight();
|
||||||
|
if (textLine.length == 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var reSpaces = /^\s*$/;
|
||||||
|
var tabLine = textLine.split("\t");
|
||||||
|
var wrapSplits = [];
|
||||||
|
|
||||||
|
var screenColumn = 0;
|
||||||
|
var documentColumn = 0;
|
||||||
|
var lastSplitColumn = 0;
|
||||||
|
|
||||||
|
var value;
|
||||||
|
var addedNewSplit;
|
||||||
|
|
||||||
|
function addSplit(incrDocumentColumn) {
|
||||||
|
var valueLenLeadingWhitespaces;
|
||||||
|
value = value.substring(incrDocumentColumn);
|
||||||
|
valueLenLeadingWhitespaces = value.length;
|
||||||
|
value = value.trimLeft();
|
||||||
|
|
||||||
|
incrDocumentColumn += valueLenLeadingWhitespaces - value.length;
|
||||||
|
|
||||||
|
// If there was a split saved before, then add it to the resulting
|
||||||
|
// array. It's not possible to store the split column here directly,
|
||||||
|
// as there migth be tabs/spaces following the current column that
|
||||||
|
// will cause the split position to get incremented.
|
||||||
|
if (lastSplitColumn) {
|
||||||
|
wrapSplits.push(lastSplitColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastSplitColumn = documentColumn += incrDocumentColumn;
|
||||||
|
screenColumn = 0;
|
||||||
|
|
||||||
|
addedNewSplit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < tabLine.length; i++) {
|
||||||
|
value = tabLine[i];
|
||||||
|
while (screenColumn + value.length >= wrapLimit) {
|
||||||
|
// Find the last space that we use to split the line.
|
||||||
|
var lastSpaceIdx =
|
||||||
|
value.substring(0, wrapLimit - screenColumn + 1).
|
||||||
|
lastIndexOf(" ");
|
||||||
|
|
||||||
|
// There is no space to break the line.
|
||||||
|
if (lastSpaceIdx == -1) {
|
||||||
|
// True if this is the first tabLine we face
|
||||||
|
// during this split. This means, there is no
|
||||||
|
// space or tab to make the split -> force split.
|
||||||
|
if (screenColumn == 0) {
|
||||||
|
addSplit(wrapLimit);
|
||||||
|
}
|
||||||
|
// True if we've added some content in this split line
|
||||||
|
// already. Add a split after this already existing content
|
||||||
|
// in the split.
|
||||||
|
else {
|
||||||
|
addSplit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There is at least one space to wrap the line at.
|
||||||
|
else {
|
||||||
|
addSplit(lastSpaceIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new content to the current split.
|
||||||
|
if (!addedNewSplit) {
|
||||||
|
screenColumn += value.length + tabSize;
|
||||||
|
documentColumn += value.length + 1;
|
||||||
|
}
|
||||||
|
// True if at least one new split was added during the while loop.
|
||||||
|
else {
|
||||||
|
var lenBefore = value.length;
|
||||||
|
value = value.trimLeft();
|
||||||
|
|
||||||
|
// True if value has some content. This content goes directly
|
||||||
|
// after the last split.
|
||||||
|
// If there is no content but we are in the last tabLine, we
|
||||||
|
// already know that there is no following tabLine and we can
|
||||||
|
// shortcut by using this if instead of the following else.
|
||||||
|
if (value.length != 0 || i == tabLine.length - 1) {
|
||||||
|
documentColumn = lastSplitColumn += lenBefore - value.length;
|
||||||
|
screenColumn += value.length;
|
||||||
|
documentColumn += 1; // The tab after this for-loop.
|
||||||
|
}
|
||||||
|
// There is no value left after the split. This means, following
|
||||||
|
// spaces and tabs have to be ignored.
|
||||||
|
else {
|
||||||
|
// Tab for this for-loop.
|
||||||
|
documentColumn = lastSplitColumn += 1;
|
||||||
|
|
||||||
|
// While the following tabLines are empty/only spaces, set
|
||||||
|
// the latest split position behind them.
|
||||||
|
while ((i + 1) < tabLine.length - 1
|
||||||
|
&& reSpaces.test(tabLine[i + 1]))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
documentColumn = lastSplitColumn += tabLine[i].length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The tabLine[i + 1] is not empty. However, the trailing
|
||||||
|
// spaces have still to be removed.
|
||||||
|
value = tabLine[i + 1];
|
||||||
|
lenBefore = value.length;
|
||||||
|
value = value.trimLeft();
|
||||||
|
documentColumn = lastSplitColumn += lenBefore - value.length;
|
||||||
|
tabLine[i + 1] = value; // Store the trimed value.
|
||||||
|
}
|
||||||
|
addedNewSplit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastSplitColumn) {
|
||||||
|
wrapSplits.push(lastSplitColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapSplits;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getRowHeight = function(config, row) {
|
||||||
|
var rows;
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
rows = 1;
|
||||||
|
} else {
|
||||||
|
rows = this.$wrapData[row].length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows * config.lineHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the width of the a string on the screen while assuming that
|
||||||
|
* the string starts at the first column on the screen.
|
||||||
|
*
|
||||||
|
* @param string str String to calculate the screen width of
|
||||||
|
* @return int number of columns for str on screen.
|
||||||
|
*/
|
||||||
|
this.$getStringScreenWidth = function(str) {
|
||||||
var screenColumn = 0;
|
var screenColumn = 0;
|
||||||
var remaining = docColumn;
|
var remaining = docColumn;
|
||||||
var line = this.getLine(row);
|
|
||||||
|
|
||||||
for (var i=0; i<line.length; i++) {
|
for (var i=0; i<str.length; i++) {
|
||||||
var c = line.charCodeAt(i);
|
var c = str.charCodeAt(i);
|
||||||
if (remaining > 0) {
|
if (remaining > 0) {
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
// tab
|
// tab
|
||||||
|
|
@ -647,7 +868,7 @@ var EditSession = function(text, mode) {
|
||||||
c >= 0x3040 && c <= 0x309F || // Hiragana
|
c >= 0x3040 && c <= 0x309F || // Hiragana
|
||||||
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
||||||
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
||||||
c >= 0xF900 && c <= 0xFAFF ||
|
c >= 0xF900 && c <= 0xFAFF ||
|
||||||
c >= 0x3400 && c <= 0x4DBF
|
c >= 0x3400 && c <= 0x4DBF
|
||||||
) {
|
) {
|
||||||
screenColumn += 2;
|
screenColumn += 2;
|
||||||
|
|
@ -658,56 +879,258 @@ var EditSession = function(text, mode) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return screenColumn;
|
||||||
|
}
|
||||||
|
|
||||||
return screenColumn;
|
this.getScreenLastRowColumn = function(screenRow, returnDocPosition) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return this.$getStringScreenWidth(this.getLine(screenRow));
|
||||||
|
}
|
||||||
|
|
||||||
|
var rowData = this.$screenToDocumentRow(screenRow);
|
||||||
|
var docRow = rowData[0],
|
||||||
|
row = rowData[1];
|
||||||
|
|
||||||
|
var start, end;
|
||||||
|
if (this.$wrapData[docRow][row]) {
|
||||||
|
start = (this.$wrapData[docRow][row - 1] || 0);
|
||||||
|
end = this.$wrapData[docRow][row];
|
||||||
|
returnDocPosition && end--;
|
||||||
|
} else {
|
||||||
|
end = this.getLine(docRow).length;
|
||||||
|
start = (this.$wrapData[docRow][row - 1] || 0);
|
||||||
|
}
|
||||||
|
if (!returnDocPosition) {
|
||||||
|
return this.$getStringScreenWidth(this.getLine(docRow).substring(start, end));
|
||||||
|
} else {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.screenToDocumentColumn = function(row, screenColumn) {
|
this.getDocumentLastRowColumn = function(docRow, docColumn) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return this.getLine(docRow).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
||||||
|
return this.getScreenLastRowColumn(screenRow, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getScreenFirstRowColumn = function(screenRow) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rowData = this.$screenToDocumentRow(screenRow);
|
||||||
|
var docRow = rowData[0],
|
||||||
|
row = rowData[1];
|
||||||
|
|
||||||
|
return this.$wrapData[docRow][row - 1] || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getRowSplitData = function(row) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return this.$wrapData[row];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns array
|
||||||
|
* - array[0]: The documentRow aquivalent.
|
||||||
|
* - array[1]: The screenRowOffset to the first documentRow on the screen.
|
||||||
|
*/
|
||||||
|
this.$screenToDocumentRow = function(row) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return [row, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapData = this.$wrapData, linesCount = this.getLength();
|
||||||
|
var docRow = 0;
|
||||||
|
while (docRow < linesCount && row >= wrapData[docRow].length + 1) {
|
||||||
|
row -= wrapData[docRow].length + 1;
|
||||||
|
docRow ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [docRow, row];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.screenToDocumentRow = function(screenRow) {
|
||||||
|
return this.$screenToDocumentRow(screenRow)[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.screenToDocumentColumn = function(screenRow, screenColumn) {
|
||||||
|
return this.screenToDocumentPosition(screenRow, screenColumn).column;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.screenToDocumentPosition = function(row, column) {
|
||||||
|
var line;
|
||||||
|
var docRow;
|
||||||
|
var docColumn;
|
||||||
|
var remaining = column;
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
docRow = row;
|
||||||
|
row = 0;
|
||||||
|
docColumn = 0;
|
||||||
|
line = this.getLine(docRow).split("\t");
|
||||||
|
} else {
|
||||||
|
var wrapData = this.$wrapData, linesCount = this.getLength();
|
||||||
|
|
||||||
|
var rowData = this.$screenToDocumentRow(row);
|
||||||
|
row = rowData[1];
|
||||||
|
docRow = rowData[0];
|
||||||
|
|
||||||
|
if (docRow >= linesCount) {
|
||||||
|
return {
|
||||||
|
row: docRow,
|
||||||
|
column: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
docColumn = wrapData[docRow][row - 1] || 0;
|
||||||
|
line = this.getLine(docRow).substring(docColumn).split("\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
var tabSize = this.getTabSize();
|
||||||
|
for (var i=0; i<line.length; i++) {
|
||||||
|
var len = line[i].length;
|
||||||
|
if (remaining >= len + tabSize) {
|
||||||
|
remaining -= (len + tabSize);
|
||||||
|
docColumn += (len + 1);
|
||||||
|
}
|
||||||
|
else if (remaining > len){
|
||||||
|
docColumn += len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
docColumn += remaining;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp docColumn.
|
||||||
|
if (docRow < linesCount && wrapData[docRow][row]) {
|
||||||
|
if (docColumn >= wrapData[docRow][row]) {
|
||||||
|
// We remove one character at the end such that the docColumn
|
||||||
|
// position returned is not associated to the next row on the
|
||||||
|
// screen.
|
||||||
|
docColumn = wrapData[docRow][row] - 1;
|
||||||
|
}
|
||||||
|
} else if (this.getLine(docRow)) {
|
||||||
|
docColumn = Math.min(docColumn, this.getLine(docRow).length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
row: docRow,
|
||||||
|
column: docColumn
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.documentToScreenColumn = function(row, docColumn) {
|
||||||
|
return this.documentToScreenPosition(row, docColumn).column;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return array[2]
|
||||||
|
* - array[0]: The number of the row on the screen (aka screenRow)
|
||||||
|
* - array[1]: The number of rows from the first docRow on the screen
|
||||||
|
* (aka screenRowOffset);
|
||||||
|
*/
|
||||||
|
this.$documentToScreenRow = function(docRow, docColumn) {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return [docRow, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapData = this.$wrapData;
|
||||||
|
var screenRow = 0;
|
||||||
|
|
||||||
|
// Handle special case where the row is outside of the range of lines.
|
||||||
|
if (docRow > wrapData.length - 1) {
|
||||||
|
return [
|
||||||
|
this.getScreenLength(),
|
||||||
|
wrapData[wrapData.length - 1].length - 1
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < docRow; i++) {
|
||||||
|
screenRow += wrapData[i].length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var screenRowOffset = 0;
|
||||||
|
while (docColumn >= wrapData[docRow][screenRowOffset]) {
|
||||||
|
screenRow ++;
|
||||||
|
screenRowOffset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [screenRow, screenRowOffset];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.documentToScreenRow = function(docRow, docColumn) {
|
||||||
|
return this.$documentToScreenRow(docRow, docColumn)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.documentToScreenPosition = function(pos, column) {
|
||||||
|
var str;
|
||||||
var tabSize = this.getTabSize();
|
var tabSize = this.getTabSize();
|
||||||
|
|
||||||
var docColumn = 0;
|
// Normalize the passed in arguments.
|
||||||
var remaining = screenColumn;
|
var row;
|
||||||
var line = this.getLine(row);
|
if (column != null) {
|
||||||
|
row = pos;
|
||||||
for(var i=0; i<line.length; i++) {
|
} else {
|
||||||
var c = line.charCodeAt(i);
|
row = pos.row;
|
||||||
|
column = pos.column;
|
||||||
if (remaining > 0) {
|
}
|
||||||
docColumn += 1;
|
|
||||||
// tab
|
if (!this.$useWrapMode) {
|
||||||
if (c == 9) {
|
str = this.getLine(row).substring(0, column);
|
||||||
if (remaining >= tabSize) {
|
column += (str.split("\t").length - 1) * (tabSize - 1);
|
||||||
remaining -= tabSize;
|
return {
|
||||||
} else {
|
row: row,
|
||||||
remaining = 0;
|
column: column
|
||||||
docColumn -= 1;
|
};
|
||||||
}
|
}
|
||||||
}
|
if (row >= this.getLength()) {
|
||||||
// CJK characters
|
return {
|
||||||
else if (
|
row: screenRow,
|
||||||
c >= 0x3040 && c <= 0x309F || // Hiragana
|
column: 0
|
||||||
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
};
|
||||||
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
}
|
||||||
c >= 0xF900 && c <= 0xFAFF ||
|
|
||||||
c >= 0x3400 && c <= 0x4DBF
|
var split;
|
||||||
) {
|
var wrapRowData = this.$wrapData[row];
|
||||||
if (remaining >= 2) {
|
var screenRow, screenRowOffset;
|
||||||
remaining -= 2;
|
var screenColumn;
|
||||||
} else {
|
var rowData = this.$documentToScreenRow(row, column);
|
||||||
remaining = 0;
|
screenRow = rowData[0];
|
||||||
docColumn -= 1;
|
screenRowOffset = rowData[1];
|
||||||
}
|
screenColumn = column - (wrapRowData[screenRowOffset - 1] || 0);
|
||||||
} else {
|
|
||||||
remaining -= 1;
|
str = this.getLine(row).substring(
|
||||||
}
|
wrapRowData[screenRowOffset - 1] || 0, column);
|
||||||
} else {
|
screenColumn += (str.split("\t").length - 1) * (tabSize - 1);
|
||||||
break;
|
|
||||||
}
|
return {
|
||||||
}
|
row: screenRow,
|
||||||
|
column: screenColumn
|
||||||
return docColumn;
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getScreenLength = function() {
|
||||||
|
if (!this.$useWrapMode) {
|
||||||
|
return this.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
var screenRows = 0;
|
||||||
|
for (var row = 0; row < this.$wrapData.length; row++) {
|
||||||
|
screenRows += this.$wrapData[row].length + 1;
|
||||||
|
}
|
||||||
|
return screenRows;
|
||||||
|
}
|
||||||
|
|
||||||
}).call(EditSession.prototype);
|
}).call(EditSession.prototype);
|
||||||
|
|
||||||
exports.EditSession = EditSession;
|
exports.EditSession = EditSession;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -128,6 +129,7 @@ var Editor =function(renderer, session) {
|
||||||
this.session.removeEventListener("change", this.$onDocumentChange);
|
this.session.removeEventListener("change", this.$onDocumentChange);
|
||||||
this.session.removeEventListener("changeMode", this.$onDocumentModeChange);
|
this.session.removeEventListener("changeMode", this.$onDocumentModeChange);
|
||||||
this.session.removeEventListener("changeTabSize", this.$onDocumentChangeTabSize);
|
this.session.removeEventListener("changeTabSize", this.$onDocumentChangeTabSize);
|
||||||
|
this.session.removeEventListener("changeWrapMode", this.$onDocumentChangeWrapMode);
|
||||||
this.session.removeEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint);
|
this.session.removeEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint);
|
||||||
this.session.removeEventListener("changeAnnotation", this.$onDocumentChangeAnnotation);
|
this.session.removeEventListener("changeAnnotation", this.$onDocumentChangeAnnotation);
|
||||||
|
|
||||||
|
|
@ -150,14 +152,16 @@ var Editor =function(renderer, session) {
|
||||||
this.$onDocumentChangeTabSize = this.renderer.updateText.bind(this.renderer);
|
this.$onDocumentChangeTabSize = this.renderer.updateText.bind(this.renderer);
|
||||||
session.addEventListener("changeTabSize", this.$onDocumentChangeTabSize);
|
session.addEventListener("changeTabSize", this.$onDocumentChangeTabSize);
|
||||||
|
|
||||||
|
this.$onDocumentChangeWrapMode = this.renderer.updateFull.bind(this.renderer);
|
||||||
|
session.addEventListener("changeWrapMode", this.$onDocumentChangeWrapMode);
|
||||||
|
|
||||||
this.$onDocumentChangeBreakpoint = this.onDocumentChangeBreakpoint.bind(this);
|
this.$onDocumentChangeBreakpoint = this.onDocumentChangeBreakpoint.bind(this);
|
||||||
this.session.addEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint);
|
this.session.addEventListener("changeBreakpoint", this.$onDocumentChangeBreakpoint);
|
||||||
|
|
||||||
this.$onDocumentChangeAnnotation = this.onDocumentChangeAnnotation.bind(this);
|
this.$onDocumentChangeAnnotation = this.onDocumentChangeAnnotation.bind(this);
|
||||||
this.session.addEventListener("changeAnnotation", this.$onDocumentChangeAnnotation);
|
this.session.addEventListener("changeAnnotation", this.$onDocumentChangeAnnotation);
|
||||||
|
|
||||||
this.selection = session.getSelection();
|
this.selection = session.getSelection();
|
||||||
this.$desiredColumn = 0;
|
|
||||||
|
|
||||||
this.$onCursorChange = this.onCursorChange.bind(this);
|
this.$onCursorChange = this.onCursorChange.bind(this);
|
||||||
this.selection.addEventListener("changeCursor", this.$onCursorChange);
|
this.selection.addEventListener("changeCursor", this.$onCursorChange);
|
||||||
|
|
@ -175,7 +179,7 @@ var Editor =function(renderer, session) {
|
||||||
this.onDocumentChangeAnnotation();
|
this.onDocumentChangeAnnotation();
|
||||||
this.renderer.scrollToRow(session.getScrollTopRow());
|
this.renderer.scrollToRow(session.getScrollTopRow());
|
||||||
this.renderer.updateFull();
|
this.renderer.updateFull();
|
||||||
|
|
||||||
this._dispatchEvent("changeSession", {
|
this._dispatchEvent("changeSession", {
|
||||||
session: session,
|
session: session,
|
||||||
oldSession: oldSession
|
oldSession: oldSession
|
||||||
|
|
@ -258,11 +262,11 @@ var Editor =function(renderer, session) {
|
||||||
this.onDocumentChange = function(e) {
|
this.onDocumentChange = function(e) {
|
||||||
var delta = e.data;
|
var delta = e.data;
|
||||||
var range = delta.range;
|
var range = delta.range;
|
||||||
|
|
||||||
this.bgTokenizer.start(range.start.row);
|
this.bgTokenizer.start(range.start.row);
|
||||||
if (range.start.row == range.end.row)
|
if (range.start.row == range.end.row)
|
||||||
var lastRow = range.end.row;
|
var lastRow = range.end.row;
|
||||||
else
|
else
|
||||||
lastRow = Infinity;
|
lastRow = Infinity;
|
||||||
this.renderer.updateLines(range.start.row, lastRow);
|
this.renderer.updateLines(range.start.row, lastRow);
|
||||||
|
|
||||||
|
|
@ -414,13 +418,11 @@ var Editor =function(renderer, session) {
|
||||||
this.onMouseDoubleClick = function(e) {
|
this.onMouseDoubleClick = function(e) {
|
||||||
this.selection.selectWord();
|
this.selection.selectWord();
|
||||||
this.$clickSelection = this.getSelectionRange();
|
this.$clickSelection = this.getSelectionRange();
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseTripleClick = function(e) {
|
this.onMouseTripleClick = function(e) {
|
||||||
this.selection.selectLine();
|
this.selection.selectLine();
|
||||||
this.$clickSelection = this.getSelectionRange();
|
this.$clickSelection = this.getSelectionRange();
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseWheel = function(e) {
|
this.onMouseWheel = function(e) {
|
||||||
|
|
@ -684,7 +686,6 @@ var Editor =function(renderer, session) {
|
||||||
var range = this.session.outdentRows(selection.getRange());
|
var range = this.session.outdentRows(selection.getRange());
|
||||||
|
|
||||||
selection.setSelectionRange(range, selection.isBackwards());
|
selection.setSelectionRange(range, selection.isBackwards());
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.toggleCommentLines = function() {
|
this.toggleCommentLines = function() {
|
||||||
|
|
@ -874,17 +875,14 @@ var Editor =function(renderer, session) {
|
||||||
|
|
||||||
this.clearSelection = function() {
|
this.clearSelection = function() {
|
||||||
this.selection.clearSelection();
|
this.selection.clearSelection();
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorTo = function(row, column) {
|
this.moveCursorTo = function(row, column) {
|
||||||
this.selection.moveCursorTo(row, column);
|
this.selection.moveCursorTo(row, column);
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorToPosition = function(pos) {
|
this.moveCursorToPosition = function(pos) {
|
||||||
this.selection.moveCursorToPosition(pos);
|
this.selection.moveCursorToPosition(pos);
|
||||||
this.$updateDesiredColumn();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -903,34 +901,16 @@ var Editor =function(renderer, session) {
|
||||||
this.navigateTo = function(row, column) {
|
this.navigateTo = function(row, column) {
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.moveCursorTo(row, column);
|
this.moveCursorTo(row, column);
|
||||||
this.$updateDesiredColumn(column);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.navigateUp = function(times) {
|
this.navigateUp = function(times) {
|
||||||
this.selection.clearSelection();
|
this.selection.clearSelection();
|
||||||
this.selection.moveCursorBy(-(times || 1), 0);
|
this.selection.moveCursorBy(-1, 0);
|
||||||
|
|
||||||
if (this.$desiredColumn) {
|
|
||||||
var cursor = this.getCursorPosition();
|
|
||||||
var column = this.session.screenToDocumentColumn(cursor.row, this.$desiredColumn);
|
|
||||||
this.selection.moveCursorTo(cursor.row, column);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.navigateDown = function(times) {
|
this.navigateDown = function(times) {
|
||||||
this.selection.clearSelection();
|
this.selection.clearSelection();
|
||||||
this.selection.moveCursorBy(times || 1, 0);
|
this.selection.moveCursorBy(1, 0);
|
||||||
|
|
||||||
if (this.$desiredColumn) {
|
|
||||||
var cursor = this.getCursorPosition();
|
|
||||||
var column = this.session.screenToDocumentColumn(cursor.row, this.$desiredColumn);
|
|
||||||
this.selection.moveCursorTo(cursor.row, column);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$updateDesiredColumn = function() {
|
|
||||||
var cursor = this.getCursorPosition();
|
|
||||||
this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.navigateLeft = function(times) {
|
this.navigateLeft = function(times) {
|
||||||
|
|
@ -999,7 +979,6 @@ var Editor =function(renderer, session) {
|
||||||
this.$tryReplace(range, replacement);
|
this.$tryReplace(range, replacement);
|
||||||
if (range !== null)
|
if (range !== null)
|
||||||
this.selection.setSelectionRange(range);
|
this.selection.setSelectionRange(range);
|
||||||
this.$updateDesiredColumn();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
this.replaceAll = function(replacement, options) {
|
this.replaceAll = function(replacement, options) {
|
||||||
|
|
@ -1018,7 +997,6 @@ var Editor =function(renderer, session) {
|
||||||
this.$tryReplace(ranges[i], replacement);
|
this.$tryReplace(ranges[i], replacement);
|
||||||
if (ranges[0] !== null)
|
if (ranges[0] !== null)
|
||||||
this.selection.setSelectionRange(ranges[0]);
|
this.selection.setSelectionRange(ranges[0]);
|
||||||
this.$updateDesiredColumn();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
this.$tryReplace = function(range, replacement) {
|
this.$tryReplace = function(range, replacement) {
|
||||||
|
|
@ -1071,7 +1049,6 @@ var Editor =function(renderer, session) {
|
||||||
var range = this.$search.find(this.session);
|
var range = this.$search.find(this.session);
|
||||||
if (range) {
|
if (range) {
|
||||||
this.gotoLine(range.end.row+1, range.end.column);
|
this.gotoLine(range.end.row+1, range.end.column);
|
||||||
this.$updateDesiredColumn();
|
|
||||||
this.selection.setSelectionRange(range);
|
this.selection.setSelectionRange(range);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -57,10 +58,9 @@ var Cursor = function(parentEl) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setCursor = function(position, overwrite) {
|
this.setCursor = function(position, overwrite) {
|
||||||
this.position = {
|
this.position =
|
||||||
row : position.row,
|
this.session.documentToScreenPosition(position);
|
||||||
column : this.session.documentToScreenColumn(position.row, position.column)
|
|
||||||
};
|
|
||||||
if (overwrite) {
|
if (overwrite) {
|
||||||
dom.addCssClass(this.cursor, "ace_overwrite");
|
dom.addCssClass(this.cursor, "ace_overwrite");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -100,7 +100,7 @@ var Cursor = function(parentEl) {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getPixelPosition = function() {
|
this.getPixelPosition = function(onScreen) {
|
||||||
if (!this.config || !this.position) {
|
if (!this.config || !this.position) {
|
||||||
return {
|
return {
|
||||||
left : 0,
|
left : 0,
|
||||||
|
|
@ -108,10 +108,12 @@ var Cursor = function(parentEl) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var cursorLeft = Math.round(this.position.column * this.config.characterWidth);
|
var pos = this.position;
|
||||||
var cursorTop = this.position.row * this.config.lineHeight;
|
var cursorLeft = Math.round(pos.column * this.config.characterWidth);
|
||||||
|
var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
|
||||||
|
this.config.lineHeight;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
left : cursorLeft,
|
left : cursorLeft,
|
||||||
top : cursorTop
|
top : cursorTop
|
||||||
};
|
};
|
||||||
|
|
@ -123,17 +125,10 @@ var Cursor = function(parentEl) {
|
||||||
|
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
var cursorLeft = Math.round(this.position.column * config.characterWidth);
|
this.pixelPos = this.getPixelPosition(true);
|
||||||
var cursorTop = this.position.row * config.lineHeight;
|
|
||||||
|
|
||||||
this.pixelPos = {
|
this.cursor.style.left = this.pixelPos.left + "px";
|
||||||
left : cursorLeft,
|
this.cursor.style.top = this.pixelPos.top + "px";
|
||||||
top : cursorTop
|
|
||||||
};
|
|
||||||
|
|
||||||
this.cursor.style.left = cursorLeft + "px";
|
|
||||||
this.cursor.style.top = (cursorTop - (config.firstRow * config.lineHeight))
|
|
||||||
+ "px";
|
|
||||||
this.cursor.style.width = config.characterWidth + "px";
|
this.cursor.style.width = config.characterWidth + "px";
|
||||||
this.cursor.style.height = config.lineHeight + "px";
|
this.cursor.style.height = config.lineHeight + "px";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -51,12 +52,16 @@ var Gutter = function(parentEl) {
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.setSession = function(session) {
|
||||||
|
this.session = session;
|
||||||
|
};
|
||||||
|
|
||||||
this.addGutterDecoration = function(row, className){
|
this.addGutterDecoration = function(row, className){
|
||||||
if (!this.$decorations[row])
|
if (!this.$decorations[row])
|
||||||
this.$decorations[row] = "";
|
this.$decorations[row] = "";
|
||||||
this.$decorations[row] += " ace_" + className;
|
this.$decorations[row] += " ace_" + className;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeGutterDecoration = function(row, className){
|
this.removeGutterDecoration = function(row, className){
|
||||||
this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
|
this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
|
||||||
};
|
};
|
||||||
|
|
@ -101,7 +106,7 @@ var Gutter = function(parentEl) {
|
||||||
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
||||||
annotation.className,
|
annotation.className,
|
||||||
"' title='", annotation.text.join("\n"),
|
"' title='", annotation.text.join("\n"),
|
||||||
"' style='height:", config.lineHeight, "px;'>", (i+1), "</div>");
|
"' style='height:", this.session.getRowHeight(config, i), "px;'>", (i+1), "</div>");
|
||||||
html.push("</div>");
|
html.push("</div>");
|
||||||
}
|
}
|
||||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -87,6 +88,8 @@ var Marker = function(parentEl) {
|
||||||
var range = marker.range.clipRows(config.firstRow, config.lastRow);
|
var range = marker.range.clipRows(config.firstRow, config.lastRow);
|
||||||
if (range.isEmpty()) continue;
|
if (range.isEmpty()) continue;
|
||||||
|
|
||||||
|
range = range.toScreenRange(this.session);
|
||||||
|
|
||||||
if (range.isMultiLine()) {
|
if (range.isMultiLine()) {
|
||||||
if (marker.type == "text") {
|
if (marker.type == "text") {
|
||||||
this.drawTextMarker(html, range, marker.clazz, config);
|
this.drawTextMarker(html, range, marker.clazz, config);
|
||||||
|
|
@ -101,11 +104,16 @@ var Marker = function(parentEl) {
|
||||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
this.element = dom.setInnerHtml(this.element, html.join(""));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
this.$getTop = function(row, layerConfig) {
|
||||||
|
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||||
// selection start
|
// selection start
|
||||||
var row = range.start.row;
|
var row = range.start.row;
|
||||||
var lineRange = new Range(row, range.start.column, row, this.session.getLine(row).length);
|
|
||||||
|
var lineRange = new Range(row, range.start.column,
|
||||||
|
row, this.session.getScreenLastRowColumn(row));
|
||||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||||
|
|
||||||
// selection end
|
// selection end
|
||||||
|
|
@ -116,18 +124,16 @@ var Marker = function(parentEl) {
|
||||||
for (var row = range.start.row + 1; row < range.end.row; row++) {
|
for (var row = range.start.row + 1; row < range.end.row; row++) {
|
||||||
lineRange.start.row = row;
|
lineRange.start.row = row;
|
||||||
lineRange.end.row = row;
|
lineRange.end.row = row;
|
||||||
lineRange.end.column = this.session.getLine(row).length; // account for endofline characters
|
lineRange.end.column = this.session.getScreenLastRowColumn(row);
|
||||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||||
var range = range.toScreenRange(this.session);
|
|
||||||
|
|
||||||
// from selection start to the end of the line
|
// from selection start to the end of the line
|
||||||
var height = layerConfig.lineHeight;
|
var height = layerConfig.lineHeight;
|
||||||
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
|
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
|
||||||
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
var top = this.$getTop(range.start.row, layerConfig);
|
||||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||||
|
|
||||||
stringBuilder.push(
|
stringBuilder.push(
|
||||||
|
|
@ -139,7 +145,7 @@ var Marker = function(parentEl) {
|
||||||
);
|
);
|
||||||
|
|
||||||
// from start of the last line to the selection end
|
// from start of the last line to the selection end
|
||||||
var top = (range.end.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
var top = this.$getTop(range.end.row, layerConfig);
|
||||||
var width = Math.round(range.end.column * layerConfig.characterWidth);
|
var width = Math.round(range.end.column * layerConfig.characterWidth);
|
||||||
|
|
||||||
stringBuilder.push(
|
stringBuilder.push(
|
||||||
|
|
@ -153,7 +159,7 @@ var Marker = function(parentEl) {
|
||||||
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
|
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
|
||||||
if (height < 0)
|
if (height < 0)
|
||||||
return;
|
return;
|
||||||
var top = (range.start.row + 1 - layerConfig.firstRow) * layerConfig.lineHeight;
|
var top = this.$getTop(range.start.row + 1, layerConfig);
|
||||||
|
|
||||||
stringBuilder.push(
|
stringBuilder.push(
|
||||||
"<div class='", clazz, "' style='",
|
"<div class='", clazz, "' style='",
|
||||||
|
|
@ -164,11 +170,9 @@ var Marker = function(parentEl) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) {
|
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) {
|
||||||
var range = range.toScreenRange(this.session);
|
|
||||||
|
|
||||||
var height = layerConfig.lineHeight;
|
var height = layerConfig.lineHeight;
|
||||||
var width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
|
var width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
|
||||||
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
var top = this.$getTop(range.start.row, layerConfig);
|
||||||
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
var left = Math.round(range.start.column * layerConfig.characterWidth);
|
||||||
|
|
||||||
stringBuilder.push(
|
stringBuilder.push(
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -96,15 +97,15 @@ var Text = function(parentEl) {
|
||||||
if (!this.$measureNode) {
|
if (!this.$measureNode) {
|
||||||
var measureNode = this.$measureNode = document.createElement("div");
|
var measureNode = this.$measureNode = document.createElement("div");
|
||||||
var style = measureNode.style;
|
var style = measureNode.style;
|
||||||
|
|
||||||
style.width = style.height = "auto";
|
style.width = style.height = "auto";
|
||||||
style.left = style.top = "-1000px";
|
style.left = style.top = "-1000px";
|
||||||
|
|
||||||
style.visibility = "hidden";
|
style.visibility = "hidden";
|
||||||
style.position = "absolute";
|
style.position = "absolute";
|
||||||
style.overflow = "visible";
|
style.overflow = "visible";
|
||||||
style.whiteSpace = "nowrap";
|
style.whiteSpace = "nowrap";
|
||||||
|
|
||||||
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
|
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
|
||||||
// that's why we have to measure many characters
|
// that's why we have to measure many characters
|
||||||
// Note: characterWidth can be a float!
|
// Note: characterWidth can be a float!
|
||||||
|
|
@ -133,7 +134,7 @@ var Text = function(parentEl) {
|
||||||
this.setShowInvisibles = function(showInvisibles) {
|
this.setShowInvisibles = function(showInvisibles) {
|
||||||
if (this.showInvisibles == showInvisibles)
|
if (this.showInvisibles == showInvisibles)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.showInvisibles = showInvisibles;
|
this.showInvisibles = showInvisibles;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
@ -152,23 +153,31 @@ var Text = function(parentEl) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateLines = function(layerConfig, firstRow, lastRow) {
|
this.updateLines = function(config, firstRow, lastRow) {
|
||||||
this.$computeTabString();
|
this.$computeTabString();
|
||||||
this.config = layerConfig;
|
// Due to wrap line changes there can be new lines if e.g.
|
||||||
|
// the line to updated wrapped in the meantime.
|
||||||
var first = Math.max(firstRow, layerConfig.firstRow);
|
if (this.config.lastRow != config.lastRow ||
|
||||||
var last = Math.min(lastRow, layerConfig.lastRow);
|
this.config.firstRow != config.firstRow) {
|
||||||
|
this.scrollLines(config);
|
||||||
|
}
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
|
var first = Math.max(firstRow, config.firstRow);
|
||||||
|
var last = Math.min(lastRow, config.lastRow);
|
||||||
|
|
||||||
var lineElements = this.element.childNodes;
|
var lineElements = this.element.childNodes;
|
||||||
var tokens = this.tokenizer.getTokens(first, last);
|
var tokens = this.tokenizer.getTokens(first, last);
|
||||||
for (var i=first; i<=last; i++) {
|
for (var i=first; i<=last; i++) {
|
||||||
var lineElement = lineElements[i - layerConfig.firstRow];
|
var lineElement = lineElements[i - config.firstRow];
|
||||||
if (!lineElement)
|
if (!lineElement)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
this.$renderLine(html, i, tokens[i-first].tokens);
|
this.$renderLine(html, i, tokens[i-first].tokens);
|
||||||
dom.setInnerHtml(lineElement, html.join(""));
|
lineElement = dom.setInnerHtml(lineElement, html.join(""));
|
||||||
|
lineElement.style.height =
|
||||||
|
this.session.getRowHeight(config, i) + "px";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -200,7 +209,7 @@ var Text = function(parentEl) {
|
||||||
else
|
else
|
||||||
el.appendChild(fragment);
|
el.appendChild(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.lastRow > oldConfig.lastRow) {
|
if (config.lastRow > oldConfig.lastRow) {
|
||||||
var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
|
var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
|
||||||
el.appendChild(fragment);
|
el.appendChild(fragment);
|
||||||
|
|
@ -214,7 +223,7 @@ var Text = function(parentEl) {
|
||||||
var lineEl = document.createElement("div");
|
var lineEl = document.createElement("div");
|
||||||
lineEl.className = "ace_line";
|
lineEl.className = "ace_line";
|
||||||
var style = lineEl.style;
|
var style = lineEl.style;
|
||||||
style.height = this.$characterSize.height + "px";
|
style.height = this.session.getRowHeight(config, row) + "px";
|
||||||
style.width = config.width + "px";
|
style.width = config.width + "px";
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
|
|
@ -231,14 +240,12 @@ var Text = function(parentEl) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow);
|
var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow)
|
||||||
for (var i=config.firstRow; i<=config.lastRow; i++) {
|
var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow);
|
||||||
html.push("<div class='ace_line' style='height:" + this.$characterSize.height + "px;", "width:",
|
|
||||||
config.width, "px'>");
|
|
||||||
this.$renderLine(html, i, tokens[i-config.firstRow].tokens), html.push("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
// Clear the current content of the element and add the rendered fragment.
|
||||||
|
this.element.innerHTML = "";
|
||||||
|
this.element.appendChild(fragment);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$textToken = {
|
this.$textToken = {
|
||||||
|
|
@ -258,7 +265,7 @@ var Text = function(parentEl) {
|
||||||
var space = new Array(space.length+1).join(self.SPACE_CHAR);
|
var space = new Array(space.length+1).join(self.SPACE_CHAR);
|
||||||
return "<span class='ace_invisible'>" + space + "</span>";
|
return "<span class='ace_invisible'>" + space + "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -266,27 +273,62 @@ var Text = function(parentEl) {
|
||||||
var spaceReplace = " ";
|
var spaceReplace = " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
var characterWidth = this.config.characterWidth;
|
var _self = this;
|
||||||
|
function addToken(token, value) {
|
||||||
for ( var i = 0; i < tokens.length; i++) {
|
var output = value
|
||||||
var token = tokens[i];
|
|
||||||
|
|
||||||
var output = token.value
|
|
||||||
.replace(/&/g, "&")
|
.replace(/&/g, "&")
|
||||||
.replace(/</g, "<")
|
.replace(/</g, "<")
|
||||||
.replace(spaceRe, spaceReplace)
|
.replace(spaceRe, spaceReplace)
|
||||||
.replace(/\t/g, this.$tabString)
|
.replace(/\t/g, this.$tabString)
|
||||||
.replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
|
.replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
|
||||||
return "<span class='ace_cjk' style='width:" + (characterWidth * 2) + "px'>" + c + "</span>"
|
return "<span class='ace_cjk' style='width:" + (characterWidth * 2) + "px'>" + c + "</span>"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!this.$textToken[token.type]) {
|
if (!_self.$textToken[token.type]) {
|
||||||
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
||||||
stringBuilder.push("<span class='", classes, "'>", output, "</span>");
|
stringBuilder.push("<span class='", classes, "'>", output, "</span>");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stringBuilder.push(output);
|
stringBuilder.push(output);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var splits = this.session.getRowSplitData(row);
|
||||||
|
var chars = 0, split = 0, splitChars;
|
||||||
|
|
||||||
|
if (!splits || splits.length == 0) {
|
||||||
|
splitChars = Number.MAX_VALUE;
|
||||||
|
} else {
|
||||||
|
splitChars = splits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
stringBuilder.push("<div style='height:",
|
||||||
|
this.config.lineHeight, "px",
|
||||||
|
"'>");
|
||||||
|
for (var i = 0; i < tokens.length; i++) {
|
||||||
|
var token = tokens[i];
|
||||||
|
var value = token.value;
|
||||||
|
|
||||||
|
if (chars + value.length < splitChars) {
|
||||||
|
addToken(token, value);
|
||||||
|
chars += value.length;
|
||||||
|
} else {
|
||||||
|
while (chars + value.length >= splitChars) {
|
||||||
|
addToken(token, value.substring(0, splitChars - chars));
|
||||||
|
value = value.substring(splitChars - chars);
|
||||||
|
chars = splitChars;
|
||||||
|
stringBuilder.push("</div>",
|
||||||
|
"<div style='height:",
|
||||||
|
this.config.lineHeight, "px",
|
||||||
|
"'>");
|
||||||
|
split ++;
|
||||||
|
splitChars = splits[split] || Number.MAX_VALUE;
|
||||||
|
}
|
||||||
|
if (value.length != 0) {
|
||||||
|
chars += value.length;
|
||||||
|
addToken(token, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.showInvisibles) {
|
if (this.showInvisibles) {
|
||||||
|
|
@ -296,6 +338,7 @@ var Text = function(parentEl) {
|
||||||
stringBuilder.push("<span class='ace_invisible'>" + this.EOF_CHAR + "</span>");
|
stringBuilder.push("<span class='ace_invisible'>" + this.EOF_CHAR + "</span>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stringBuilder.push("</div>");
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(Text.prototype);
|
}).call(Text.prototype);
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
||||||
this.clone = function() {
|
this.clone = function() {
|
||||||
return Range.fromPoints(this.start, this.end);
|
return Range.fromPoints(this.start, this.end);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.collapseRows = function() {
|
this.collapseRows = function() {
|
||||||
if (this.end.column == 0)
|
if (this.end.column == 0)
|
||||||
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
|
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
|
||||||
|
|
@ -145,10 +145,14 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
||||||
return new Range(this.start.row, 0, this.end.row, 0)
|
return new Range(this.start.row, 0, this.end.row, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.toScreenRange = function(doc) {
|
this.toScreenRange = function(session) {
|
||||||
|
var screenPosStart =
|
||||||
|
session.documentToScreenPosition(this.start);
|
||||||
|
var screenPosEnd =
|
||||||
|
session.documentToScreenPosition(this.end);
|
||||||
return new Range(
|
return new Range(
|
||||||
this.start.row, doc.documentToScreenColumn(this.start.row, this.start.column),
|
screenPosStart.row, screenPosStart.column,
|
||||||
this.end.row, doc.documentToScreenColumn(this.end.row, this.end.column)
|
screenPosEnd.row, screenPosEnd.column
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -165,11 +166,19 @@ var Selection = function(doc) {
|
||||||
this.setSelectionRange = function(range, reverse) {
|
this.setSelectionRange = function(range, reverse) {
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
this.setSelectionAnchor(range.end.row, range.end.column);
|
this.setSelectionAnchor(range.end.row, range.end.column);
|
||||||
this.selectTo(range.start.row, range.start.column);
|
this.selectTo(range.start.row, range.start.column);
|
||||||
} else {
|
} else {
|
||||||
this.setSelectionAnchor(range.start.row, range.start.column);
|
this.setSelectionAnchor(range.start.row, range.start.column);
|
||||||
this.selectTo(range.end.row, range.end.column);
|
this.selectTo(range.end.row, range.end.column);
|
||||||
}
|
}
|
||||||
|
this.$updateDesiredColumn();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$updateDesiredColumn = function() {
|
||||||
|
var cursor = this.getCursor();
|
||||||
|
if (cursor) {
|
||||||
|
this.$desiredColumn = this.doc.documentToScreenColumn(cursor.row, cursor.column);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$moveSelection = function(mover) {
|
this.$moveSelection = function(mover) {
|
||||||
|
|
@ -248,7 +257,7 @@ var Selection = function(doc) {
|
||||||
var column = cursor.column;
|
var column = cursor.column;
|
||||||
var range = this.doc.getWordRange(cursor.row, column);
|
var range = this.doc.getWordRange(cursor.row, column);
|
||||||
this.setSelectionRange(range);
|
this.setSelectionRange(range);
|
||||||
|
|
||||||
/*this.setSelectionAnchor(cursor.row, start);
|
/*this.setSelectionAnchor(cursor.row, start);
|
||||||
this.$moveSelection(function() {
|
this.$moveSelection(function() {
|
||||||
this.moveCursorTo(cursor.row, end);
|
this.moveCursorTo(cursor.row, end);
|
||||||
|
|
@ -272,7 +281,7 @@ var Selection = function(doc) {
|
||||||
|
|
||||||
this.moveCursorLeft = function() {
|
this.moveCursorLeft = function() {
|
||||||
if (this.selectionLead.column == 0) {
|
if (this.selectionLead.column == 0) {
|
||||||
// cursor is a line start
|
// cursor is a line (start
|
||||||
if (this.selectionLead.row > 0) {
|
if (this.selectionLead.row > 0) {
|
||||||
this.moveCursorTo(this.selectionLead.row - 1, this.doc
|
this.moveCursorTo(this.selectionLead.row - 1, this.doc
|
||||||
.getLine(this.selectionLead.row - 1).length);
|
.getLine(this.selectionLead.row - 1).length);
|
||||||
|
|
@ -309,19 +318,27 @@ var Selection = function(doc) {
|
||||||
this.moveCursorLineStart = function() {
|
this.moveCursorLineStart = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.selectionLead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.selectionLead.column;
|
||||||
var beforeCursor = this.doc.getLine(row).slice(0, column);
|
var screenRow = this.doc.documentToScreenRow(row, column);
|
||||||
|
var firstRowColumn = this.doc.getScreenFirstRowColumn(screenRow);
|
||||||
|
var beforeCursor = this.doc.getLine(row).slice(firstRowColumn, column);
|
||||||
var leadingSpace = beforeCursor.match(/^\s*/);
|
var leadingSpace = beforeCursor.match(/^\s*/);
|
||||||
if (leadingSpace[0].length == 0)
|
if (leadingSpace[0].length == 0) {
|
||||||
this.moveCursorTo(row, this.doc.getLine(row).match(/^\s*/)[0].length);
|
var lastRowColumn = this.doc.getDocumentLastRowColumn(row, column);
|
||||||
else if (leadingSpace[0].length >= column)
|
leadingSpace = this.doc.getLine(row).
|
||||||
this.moveCursorTo(row, 0);
|
substring(firstRowColumn, lastRowColumn).
|
||||||
else
|
match(/^\s*/);
|
||||||
this.moveCursorTo(row, leadingSpace[0].length);
|
this.moveCursorTo(row, firstRowColumn + leadingSpace[0].length);
|
||||||
|
} else if (leadingSpace[0].length >= column) {
|
||||||
|
this.moveCursorTo(row, firstRowColumn);
|
||||||
|
} else {
|
||||||
|
this.moveCursorTo(row, firstRowColumn + leadingSpace[0].length);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorLineEnd = function() {
|
this.moveCursorLineEnd = function() {
|
||||||
this.moveCursorTo(this.selectionLead.row,
|
var selLead = this.selectionLead;
|
||||||
this.doc.getLine(this.selectionLead.row).length);
|
this.moveCursorTo(selLead.row,
|
||||||
|
this.doc.getDocumentLastRowColumn(selLead.row, selLead.column));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorFileEnd = function() {
|
this.moveCursorFileEnd = function() {
|
||||||
|
|
@ -387,7 +404,21 @@ var Selection = function(doc) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorBy = function(rows, chars) {
|
this.moveCursorBy = function(rows, chars) {
|
||||||
this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars);
|
if (this.doc.getUseWrapMode()) {
|
||||||
|
var screenPos = this.doc.documentToScreenPosition(
|
||||||
|
this.selectionLead.row, this.selectionLead.column);
|
||||||
|
var screenCol =
|
||||||
|
(chars == 0 && this.$desiredColumn) || screenPos.column;
|
||||||
|
|
||||||
|
var docPos = this.doc.screenToDocumentPosition(
|
||||||
|
screenPos.row + rows, screenCol);
|
||||||
|
this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
|
||||||
|
} else {
|
||||||
|
var docColumn =
|
||||||
|
(chars == 0 && this.$desiredColumn) || this.selectionLead.column;
|
||||||
|
this.moveCursorTo(
|
||||||
|
this.selectionLead.row + rows, docColumn + chars, chars == 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -395,20 +426,17 @@ var Selection = function(doc) {
|
||||||
this.moveCursorTo(position.row, position.column);
|
this.moveCursorTo(position.row, position.column);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorTo = function(row, column) {
|
this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) {
|
||||||
var cursor = this.$clipPositionToDocument(row, column);
|
var cursor = this.$clipPositionToDocument(row, column);
|
||||||
|
|
||||||
// only dispatch change if the cursor actually changed
|
// only dispatch change if the cursor actually changed
|
||||||
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
|
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
|
||||||
this.selectionLead = cursor;
|
this.selectionLead = cursor;
|
||||||
|
!preventUpdateDesiredColumn && this.$updateDesiredColumn(column);
|
||||||
this._dispatchEvent("changeCursor", { data: this.getCursor() });
|
this._dispatchEvent("changeCursor", { data: this.getCursor() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorUp = function() {
|
|
||||||
this.moveCursorBy(-1, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$clipPositionToDocument = function(row, column) {
|
this.$clipPositionToDocument = function(row, column) {
|
||||||
var pos = {};
|
var pos = {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,5 +57,5 @@ async.concat(
|
||||||
require("./mode/javascript_tokenizer_test"),
|
require("./mode/javascript_tokenizer_test"),
|
||||||
require("./mode/text_test"),
|
require("./mode/text_test"),
|
||||||
require("./mode/xml_test"),
|
require("./mode/xml_test"),
|
||||||
require("./mode/xml_tokenizer_test")
|
require("./mode/xml_tokenizer_test")
|
||||||
).exec();
|
).exec();
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -39,7 +40,7 @@ var Document = require("../document").Document,
|
||||||
Range = require("../range").Range,
|
Range = require("../range").Range,
|
||||||
assert = require("./assertions"),
|
assert = require("./assertions"),
|
||||||
async = require("asyncjs");
|
async = require("asyncjs");
|
||||||
|
|
||||||
var Test = {
|
var Test = {
|
||||||
|
|
||||||
"test: insert text in line" : function() {
|
"test: insert text in line" : function() {
|
||||||
|
|
@ -47,194 +48,194 @@ var Test = {
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insert({row: 0, column: 1}, "juhu");
|
doc.insert({row: 0, column: 1}, "juhu");
|
||||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert new line" : function() {
|
"test: insert new line" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insertNewLine({row: 0, column: 1});
|
doc.insertNewLine({row: 0, column: 1});
|
||||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert lines at the beginning" : function() {
|
"test: insert lines at the beginning" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insertLines(0, ["aa", "bb"]);
|
doc.insertLines(0, ["aa", "bb"]);
|
||||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert lines at the end" : function() {
|
"test: insert lines at the end" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insertLines(2, ["aa", "bb"]);
|
doc.insertLines(2, ["aa", "bb"]);
|
||||||
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert lines in the middle" : function() {
|
"test: insert lines in the middle" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insertLines(1, ["aa", "bb"]);
|
doc.insertLines(1, ["aa", "bb"]);
|
||||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert multi line string at the start" : function() {
|
"test: insert multi line string at the start" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
|
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
|
||||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert multi line string at the end" : function() {
|
"test: insert multi line string at the end" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
|
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
|
||||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: insert multi line string in the middle" : function() {
|
"test: insert multi line string in the middle" : function() {
|
||||||
var doc = new Document(["12", "34"]);
|
var doc = new Document(["12", "34"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
|
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
|
||||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["12", "34"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: delete in line" : function() {
|
"test: delete in line" : function() {
|
||||||
var doc = new Document(["1234", "5678"]);
|
var doc = new Document(["1234", "5678"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.remove(new Range(0, 1, 0, 3));
|
doc.remove(new Range(0, 1, 0, 3));
|
||||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: delete new line" : function() {
|
"test: delete new line" : function() {
|
||||||
var doc = new Document(["1234", "5678"]);
|
var doc = new Document(["1234", "5678"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.remove(new Range(0, 4, 1, 0));
|
doc.remove(new Range(0, 4, 1, 0));
|
||||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: delete multi line range line" : function() {
|
"test: delete multi line range line" : function() {
|
||||||
var doc = new Document(["1234", "5678", "abcd"]);
|
var doc = new Document(["1234", "5678", "abcd"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.remove(new Range(0, 2, 2, 2));
|
doc.remove(new Range(0, 2, 2, 2));
|
||||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||||
|
|
||||||
var d = deltas.concat();
|
var d = deltas.concat();
|
||||||
doc.revertDeltas(d);
|
doc.revertDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n"));
|
assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n"));
|
||||||
|
|
||||||
doc.applyDeltas(d);
|
doc.applyDeltas(d);
|
||||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: delete full lines" : function() {
|
"test: delete full lines" : function() {
|
||||||
var doc = new Document(["1234", "5678", "abcd"]);
|
var doc = new Document(["1234", "5678", "abcd"]);
|
||||||
|
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
doc.on("change", function(e) { deltas.push(e.data); });
|
doc.on("change", function(e) { deltas.push(e.data); });
|
||||||
|
|
||||||
doc.remove(new Range(1, 0, 3, 0));
|
doc.remove(new Range(1, 0, 3, 0));
|
||||||
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
|
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: remove lines should return the removed lines" : function() {
|
"test: remove lines should return the removed lines" : function() {
|
||||||
var doc = new Document(["1234", "5678", "abcd"]);
|
var doc = new Document(["1234", "5678", "abcd"]);
|
||||||
|
|
||||||
var removed = doc.removeLines(1, 2);
|
var removed = doc.removeLines(1, 2);
|
||||||
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
|
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
@ -246,7 +247,7 @@ var Test = {
|
||||||
|
|
||||||
"test: should handle windows style new lines" : function() {
|
"test: should handle windows style new lines" : function() {
|
||||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||||
|
|
||||||
doc.setNewLineMode("unix");
|
doc.setNewLineMode("unix");
|
||||||
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
@ -259,24 +260,86 @@ var Test = {
|
||||||
|
|
||||||
"test: set new line mode to 'unix' should use '\n' as new lines": function() {
|
"test: set new line mode to 'unix' should use '\n' as new lines": function() {
|
||||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||||
|
|
||||||
doc.setNewLineMode("unix");
|
doc.setNewLineMode("unix");
|
||||||
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: set new line mode to 'auto' should detect the incoming nl type": function() {
|
"test: set new line mode to 'auto' should detect the incoming nl type": function() {
|
||||||
var doc = new Document(["1", "2", "3"].join("\n"));
|
var doc = new Document(["1", "2", "3"].join("\n"));
|
||||||
|
|
||||||
doc.setNewLineMode("auto");
|
doc.setNewLineMode("auto");
|
||||||
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
|
||||||
|
|
||||||
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
var doc = new Document(["1", "2", "3"].join("\r\n"));
|
||||||
|
|
||||||
doc.setNewLineMode("auto");
|
doc.setNewLineMode("auto");
|
||||||
assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n"));
|
assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n"));
|
||||||
|
|
||||||
doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n"));
|
doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n"));
|
||||||
assert.equal(["4", "5", "6"].join("\n"), doc.getValue());
|
assert.equal(["4", "5", "6"].join("\n"), doc.getValue());
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: wrapLine split function" : function() {
|
||||||
|
var splits;
|
||||||
|
var tabSize = 4;
|
||||||
|
var wrapLimit = 12;
|
||||||
|
var computeWrapSplits = Document.prototype.$computeWrapSplits;
|
||||||
|
var c = 0;
|
||||||
|
|
||||||
|
function computeAndAssert(line, assertEqual) {
|
||||||
|
splits = computeWrapSplits(line, wrapLimit, tabSize);
|
||||||
|
assert.ok(splits.length == assertEqual.length);
|
||||||
|
for (var i = 0; i < splits.length; i++) {
|
||||||
|
assert.ok(splits[i] == assertEqual[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic splitting.
|
||||||
|
computeAndAssert("foo bar foo bar", [ 12 ]);
|
||||||
|
computeAndAssert("foo bar f bar", [ 12 ]);
|
||||||
|
computeAndAssert("foo bar f r", [ 14 ]);
|
||||||
|
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
|
||||||
|
|
||||||
|
// Don't split if there is only whitespaces/tabs at the end of the line.
|
||||||
|
computeAndAssert("foo foo foo \t \t", [ ]);
|
||||||
|
|
||||||
|
// If there is no space to split, force split.
|
||||||
|
computeAndAssert("foooooooooooooo", [ 12 ]);
|
||||||
|
computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]);
|
||||||
|
computeAndAssert("foo bar fooooooooooobooooooo", [8, 20]);
|
||||||
|
|
||||||
|
// Basic splitting + tabs.
|
||||||
|
computeAndAssert("foo \t\tbar", [ 6 ]);
|
||||||
|
computeAndAssert("foo \t \tbar", [ 7 ]);
|
||||||
|
|
||||||
|
// Ignore spaces/tabs at beginning of split.
|
||||||
|
computeAndAssert("foo \t \t \t \t bar", [ 14]);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: documentToScreen": function() {
|
||||||
|
var tabSize = 4;
|
||||||
|
var wrapLimit = 12;
|
||||||
|
var doc = new Document(["foo bar foo bar"]);
|
||||||
|
doc.setUseWrapMode(true);
|
||||||
|
doc.setWrapLimit(12);
|
||||||
|
|
||||||
|
assert.position(doc.documentToScreenPosition(0, 11), 0, 11);
|
||||||
|
assert.position(doc.documentToScreenPosition(0, 12), 1, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: screenToDocument": function() {
|
||||||
|
var tabSize = 4;
|
||||||
|
var wrapLimit = 12;
|
||||||
|
var doc = new Document(["foo bar foo bar"]);
|
||||||
|
doc.setUseWrapMode(true);
|
||||||
|
doc.setWrapLimit(12);
|
||||||
|
|
||||||
|
assert.position(doc.screenToDocumentPosition(1, 0), 0, 12);
|
||||||
|
assert.position(doc.screenToDocumentPosition(0, 11), 0, 11);
|
||||||
|
// Check if the position is clamped the right way.
|
||||||
|
assert.position(doc.screenToDocumentPosition(0, 12), 0, 11);
|
||||||
|
assert.position(doc.screenToDocumentPosition(0, 20), 0, 11);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -285,4 +348,4 @@ module.exports = require("asyncjs/test").testcase(Test);
|
||||||
if (module === require.main) {
|
if (module === require.main) {
|
||||||
require("../../../support/paths");
|
require("../../../support/paths");
|
||||||
exports.exec()
|
exports.exec()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
* Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
|
||||||
|
* Julian Viereck <julian.viereck@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|
@ -120,7 +121,6 @@ var VirtualRenderer = function(container, theme) {
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
this.showGutter = true;
|
this.showGutter = true;
|
||||||
|
|
||||||
this.CHANGE_CURSOR = 1;
|
this.CHANGE_CURSOR = 1;
|
||||||
|
|
@ -138,8 +138,8 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.$cursorLayer.setSession(session);
|
this.$cursorLayer.setSession(session);
|
||||||
this.$markerLayer.setSession(session);
|
this.$markerLayer.setSession(session);
|
||||||
|
this.$gutterLayer.setSession(session);
|
||||||
this.$textLayer.setSession(session);
|
this.$textLayer.setSession(session);
|
||||||
|
|
||||||
this.$loop.schedule(this.CHANGE_FULL);
|
this.$loop.schedule(this.CHANGE_FULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -327,14 +327,14 @@ var VirtualRenderer = function(container, theme) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$updateScrollBar = function() {
|
this.$updateScrollBar = function() {
|
||||||
this.scrollBar.setInnerHeight(this.session.getLength() * this.lineHeight);
|
this.scrollBar.setInnerHeight(this.session.getScreenLength() * this.lineHeight);
|
||||||
this.scrollBar.setScrollTop(this.scrollTop);
|
this.scrollBar.setScrollTop(this.scrollTop);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$renderChanges = function(changes) {
|
this.$renderChanges = function(changes) {
|
||||||
if (!changes || !this.session || !this.$tokenizer)
|
if (!changes || !this.session || !this.$tokenizer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// text, scrolling and resize changes can cause the view port size to change
|
// text, scrolling and resize changes can cause the view port size to change
|
||||||
if (!this.layerConfig ||
|
if (!this.layerConfig ||
|
||||||
changes & this.CHANGE_FULL ||
|
changes & this.CHANGE_FULL ||
|
||||||
|
|
@ -352,6 +352,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.$markerLayer.update(this.layerConfig);
|
this.$markerLayer.update(this.layerConfig);
|
||||||
this.$cursorLayer.update(this.layerConfig);
|
this.$cursorLayer.update(this.layerConfig);
|
||||||
this.$updateScrollBar();
|
this.$updateScrollBar();
|
||||||
|
this.scrollCursorIntoView();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,20 +393,36 @@ var VirtualRenderer = function(container, theme) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$computeLayerConfig = function() {
|
this.$computeLayerConfig = function() {
|
||||||
|
var session = this.session;
|
||||||
|
|
||||||
var offset = this.scrollTop % this.lineHeight;
|
var offset = this.scrollTop % this.lineHeight;
|
||||||
var minHeight = this.$size.scrollerHeight + this.lineHeight;
|
var minHeight = this.$size.scrollerHeight + this.lineHeight;
|
||||||
|
|
||||||
var longestLine = this.$getLongestLine();
|
var longestLine = this.$getLongestLine();
|
||||||
var widthChanged = !this.layerConfig ? true : (this.layerConfig.width != longestLine);
|
var widthChanged = !this.layerConfig ? true : (this.layerConfig.width != longestLine);
|
||||||
|
|
||||||
var lineCount = Math.ceil(minHeight / this.lineHeight);
|
var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
|
||||||
var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
|
var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
|
||||||
var lastRow = Math.max(0, Math.min(this.session.getLength(), firstRow + lineCount) - 1);
|
var lastRow = firstRow + lineCount;
|
||||||
|
|
||||||
|
// Map lines on the screen to lines in the document.
|
||||||
|
var firstRowScreen, firstRowHeight;
|
||||||
|
var lineHeight = { lineHeight: this.lineHeight };
|
||||||
|
firstRow = session.screenToDocumentRow(firstRow);
|
||||||
|
firstRowScreen = session.documentToScreenRow(firstRow);
|
||||||
|
firstRowHeight = session.getRowHeight(lineHeight, firstRow);
|
||||||
|
|
||||||
|
lastRow = Math.min(session.screenToDocumentRow(lastRow), session.getLength() - 1);
|
||||||
|
minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+
|
||||||
|
firstRowHeight;
|
||||||
|
|
||||||
|
offset = this.scrollTop - firstRowScreen * this.lineHeight;
|
||||||
|
|
||||||
var layerConfig = this.layerConfig = {
|
var layerConfig = this.layerConfig = {
|
||||||
width : longestLine,
|
width : longestLine,
|
||||||
padding : this.$padding,
|
padding : this.$padding,
|
||||||
firstRow : firstRow,
|
firstRow : firstRow,
|
||||||
|
firstRowScreen: firstRowScreen,
|
||||||
lastRow : lastRow,
|
lastRow : lastRow,
|
||||||
lineHeight : this.lineHeight,
|
lineHeight : this.lineHeight,
|
||||||
characterWidth : this.characterWidth,
|
characterWidth : this.characterWidth,
|
||||||
|
|
@ -540,7 +557,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.scrollToY = function(scrollTop) {
|
this.scrollToY = function(scrollTop) {
|
||||||
var maxHeight = this.session.getLength() * this.lineHeight - this.$size.scrollerHeight;
|
var maxHeight = this.session.getScreenLength() * this.lineHeight - this.$size.scrollerHeight;
|
||||||
var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop));
|
var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop));
|
||||||
|
|
||||||
if (this.scrollTop !== scrollTop) {
|
if (this.scrollTop !== scrollTop) {
|
||||||
|
|
@ -569,17 +586,15 @@ var VirtualRenderer = function(container, theme) {
|
||||||
var row = Math.floor((pageY + this.scrollTop - canvasPos.top)
|
var row = Math.floor((pageY + this.scrollTop - canvasPos.top)
|
||||||
/ this.lineHeight);
|
/ this.lineHeight);
|
||||||
|
|
||||||
return {
|
return this.session.screenToDocumentPosition(row, Math.max(col, 0));
|
||||||
row : row,
|
|
||||||
column : this.session.screenToDocumentColumn(Math.max(0, Math.min(row, this.session.getLength()-1)), col)
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.textToScreenCoordinates = function(row, column) {
|
this.textToScreenCoordinates = function(row, column) {
|
||||||
var canvasPos = this.scroller.getBoundingClientRect();
|
var canvasPos = this.scroller.getBoundingClientRect();
|
||||||
|
var pos = this.session.documentToScreenPosition(row, column);
|
||||||
|
|
||||||
var x = this.$padding + Math.round(this.session.documentToScreenColumn(row, column) * this.characterWidth);
|
var x = this.$padding + Math.round(pos.column * this.characterWidth);
|
||||||
var y = row * this.lineHeight;
|
var y = pos.row * this.lineHeight;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageX: canvasPos.left + x - this.getScrollLeft(),
|
pageX: canvasPos.left + x - this.getScrollLeft(),
|
||||||
|
|
@ -604,7 +619,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$composition.innerHTML = " ";
|
this.$composition.innerHTML = " ";
|
||||||
|
|
||||||
var pos = this.$cursorLayer.getPixelPosition();
|
var pos = this.$cursorLayer.getPixelPosition();
|
||||||
var style = this.$composition.style;
|
var style = this.$composition.style;
|
||||||
style.top = pos.top + "px";
|
style.top = pos.top + "px";
|
||||||
|
|
@ -624,7 +639,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
|
|
||||||
if (!this.$composition)
|
if (!this.$composition)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var style = this.$composition.style;
|
var style = this.$composition.style;
|
||||||
style.top = "-10000px";
|
style.top = "-10000px";
|
||||||
style.left = "-10000px";
|
style.left = "-10000px";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
require("./requireJS-node");
|
require("./requireJS-node");
|
||||||
require.paths.unshift(__dirname + "/../lib");
|
require.paths.unshift(__dirname + "/../lib");
|
||||||
require.paths.unshift(__dirname + "/pilot/lib");
|
require.paths.unshift(__dirname + "/pilot/lib");
|
||||||
require.paths.unshift(__dirname);
|
require.paths.unshift(__dirname);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue