diff --git a/ace/editor.js b/ace/editor.js index 12b91ccc..eeba1a33 100644 --- a/ace/editor.js +++ b/ace/editor.js @@ -825,73 +825,43 @@ var Editor = function(windowView, buffer) { }; this.navigateUp = function(times) { - this.selection.clearSelection(); - times = times || 1; - this.selection.moveCursorBy(-times, 0); + this.windowModel.navigateUp(times); }; this.navigateDown = function(times) { - this.selection.clearSelection(); - times = times || 1; - this.selection.moveCursorBy(times, 0); + this.windowModel.navigateDown(times); }; this.navigateLeft = function(times) { - if (!this.selection.isEmpty()) { - var selectionStart = this.getSelectionRange().start; - this.moveCursorToPosition(selectionStart); - } - else { - times = times || 1; - while (times--) { - this.selection.moveCursorLeft(); - } - } - this.clearSelection(); + this.windowModel.navigateLeft(times); }; this.navigateRight = function(times) { - if (!this.selection.isEmpty()) { - var selectionEnd = this.getSelectionRange().end; - this.moveCursorToPosition(selectionEnd); - } - else { - times = times || 1; - while (times--) { - this.selection.moveCursorRight(); - } - } - this.clearSelection(); + this.windowModel.navigateRight(times); }; this.navigateLineStart = function() { - this.selection.moveCursorLineStart(); - this.clearSelection(); + this.windowModel.navigateLineStart() }; this.navigateLineEnd = function() { - this.selection.moveCursorLineEnd(); - this.clearSelection(); + this.windowModel.navigateLineEnd(); }; this.navigateFileEnd = function() { - this.selection.moveCursorFileEnd(); - this.clearSelection(); + this.windowModel.navigateFileEnd(); }; this.navigateFileStart = function() { - this.selection.moveCursorFileStart(); - this.clearSelection(); + this.windowModel.navigateFileStart(); }; this.navigateWordRight = function() { - this.selection.moveCursorWordRight(); - this.clearSelection(); + this.windowModel.navigateWordRight(); }; this.navigateWordLeft = function() { - this.selection.moveCursorWordLeft(); - this.clearSelection(); + this.windowModel.navigateWordLeft(); }; this.replace = function(replacement, options) { diff --git a/ace/editor_navigation_test.js b/ace/editor_navigation_test.js index 9fc4c3c8..296ffaae 100644 --- a/ace/editor_navigation_test.js +++ b/ace/editor_navigation_test.js @@ -37,143 +37,174 @@ if (typeof process !== "undefined") { require("../support/paths"); - require("ace/test/mockdom"); } define(function(require, exports, module) { var Buffer = require("ace/model/buffer").Buffer; var Window = require("ace/model/window").Window; -var Editor = require("ace/editor").Editor; -var MockRenderer = require("ace/view/window_view_mock").MockRenderer; +var WindowController = require("ace/window_controller").WindowController; +var WindowViewMock = require("ace/view/window_view_mock").WindowViewMock; var assert = require("ace/test/assertions"); module.exports = { name: "editor navigation", + setUp: function() { + this.win = new Window({}); + this.winController = new WindowController(this.win, new WindowViewMock()); + this.win.setSizes({ + heigth: 410, + width: 640, + scrollerHeight: 400, + scrollerWidth: 600 + }); + this.win.setComputedCharacterSize({width: 10, height: 20}); + this.update(); + }, + createBuffer : function(rows, cols) { var line = new Array(cols + 1).join("a"); var text = new Array(rows).join(line + "\n") + line; return new Buffer(text); }, + + update: function() { + this.win.updateLayerConfig(); + }, "test: navigate to end of file should scroll the last line into view" : function() { - var doc = this.createBuffer(200, 10); - var editor = new Editor(new MockRenderer(), doc); + var win = this.win; + win.setBuffer(this.createBuffer(200, 10)); - editor.navigateFileEnd(); - var cursor = editor.getCursorPosition(); + win.navigateFileEnd(); + this.update(); + var cursor = win.getCursorPosition(); - assert.ok(editor.getFirstVisibleRow() <= cursor.row); - assert.ok(editor.getLastVisibleRow() >= cursor.row); + assert.ok(win.getFirstVisibleRow() <= cursor.row); + assert.ok(win.getLastVisibleRow() >= cursor.row); }, "test: navigate to start of file should scroll the first row into view" : function() { - var doc = this.createBuffer(200, 10); - var editor = new Editor(new MockRenderer(), doc); + var win = this.win; + win.setBuffer(this.createBuffer(200, 10)); - editor.moveCursorTo(editor.getLastVisibleRow() + 20); - editor.navigateFileStart(); + win.moveCursorTo(win.getLastVisibleRow() + 20); + this.update(); + win.navigateFileStart(); + this.update(); - assert.equal(editor.getFirstVisibleRow(), 0); + assert.equal(win.getFirstVisibleRow(), 0); }, - ">test: goto hidden line should scroll the line into the middle of the viewport" : function() { - //var editor = new Editor(new MockRenderer(), this.createBuffer(200, 5)); - var win = new Window(); + "test: goto hidden line should scroll the line into the middle of the viewport" : function() { + var win = this.win; win.setBuffer(this.createBuffer(200, 5)); - win.setSizes({ - heigth: 410, - width: 640, - scrollerHeight: 410, - scrollerWidth: 600 - }); - win.setComputedCharacterSize({width: 10, height: 20}); - win.updateLayerConfig(); win.navigateTo(0, 0); + this.update(); win.gotoLine(101); + this.update() assert.position(win.getCursorPosition(), 100, 0); assert.equal(win.getFirstVisibleRow(), 90); win.navigateTo(100, 0); + this.update(); win.gotoLine(11); + this.update(); assert.position(win.getCursorPosition(), 10, 0); assert.equal(win.getFirstVisibleRow(), 0); win.navigateTo(100, 0); + this.update(); win.gotoLine(6); + this.update(); assert.position(win.getCursorPosition(), 5, 0); assert.equal(0, win.getFirstVisibleRow(), 0); win.navigateTo(100, 0); + this.update(); win.gotoLine(1); + this.update(); assert.position(win.getCursorPosition(), 0, 0); assert.equal(win.getFirstVisibleRow(), 0); win.navigateTo(0, 0); + this.update(); win.gotoLine(191); + this.update(); assert.position(win.getCursorPosition(), 190, 0); assert.equal(win.getFirstVisibleRow(), 180); win.navigateTo(0, 0); + this.update(); win.gotoLine(196); + this.update(); assert.position(win.getCursorPosition(), 195, 0); assert.equal(win.getFirstVisibleRow(), 180); }, "test: goto visible line should only move the cursor and not scroll": function() { - var editor = new Editor(new MockRenderer(), this.createBuffer(200, 5)); + var win = this.win; + win.setBuffer(this.createBuffer(200, 5)); + + win.navigateTo(0, 0); + this.update(); + win.gotoLine(12); + this.update(); + assert.position(win.getCursorPosition(), 11, 0); + assert.equal(win.getFirstVisibleRow(), 0); - editor.navigateTo(0, 0); - editor.gotoLine(12); - assert.position(editor.getCursorPosition(), 11, 0); - assert.equal(editor.getFirstVisibleRow(), 0); - - editor.navigateTo(30, 0); - editor.gotoLine(33); - assert.position(editor.getCursorPosition(), 32, 0); - assert.equal(editor.getFirstVisibleRow(), 30); + win.navigateTo(30, 0); + this.update(); + assert.equal(win.getFirstVisibleRow(), 11); + win.gotoLine(25); + this.update(); + assert.position(win.getCursorPosition(), 24, 0); + assert.equal(win.getFirstVisibleRow(), 11); }, "test: navigate from the end of a long line down to a short line and back should maintain the curser column": function() { - var editor = new Editor(new MockRenderer(), new Buffer(["123456", "1"])); + var win = this.win; + win.setBuffer(new Buffer(["123456", "1"])); - editor.navigateTo(0, 6); - assert.position(editor.getCursorPosition(), 0, 6); + win.navigateTo(0, 6); + assert.position(win.getCursorPosition(), 0, 6); - editor.navigateDown(); - assert.position(editor.getCursorPosition(), 1, 1); + win.navigateDown(); + assert.position(win.getCursorPosition(), 1, 1); - editor.navigateUp(); - assert.position(editor.getCursorPosition(), 0, 6); + win.navigateUp(); + assert.position(win.getCursorPosition(), 0, 6); }, "test: reset desired column on navigate left or right": function() { - var editor = new Editor(new MockRenderer(), new Buffer(["123456", "12"])); + var win = this.win; + win.setBuffer(new Buffer(["123456", "12"])); - editor.navigateTo(0, 6); - assert.position(editor.getCursorPosition(), 0, 6); + win.navigateTo(0, 6); + assert.position(win.getCursorPosition(), 0, 6); - editor.navigateDown(); - assert.position(editor.getCursorPosition(), 1, 2); + win.navigateDown(); + assert.position(win.getCursorPosition(), 1, 2); - editor.navigateLeft(); - assert.position(editor.getCursorPosition(), 1, 1); + win.navigateLeft(); + assert.position(win.getCursorPosition(), 1, 1); - editor.navigateUp(); - assert.position(editor.getCursorPosition(), 0, 1); + win.navigateUp(); + assert.position(win.getCursorPosition(), 0, 1); }, "test: typing text should update the desired column": function() { - var editor = new Editor(new MockRenderer(), new Buffer(["1234", "1234567890"])); + var win = this.win; + win.setBuffer(new Buffer(["1234", "1234567890"])); - editor.navigateTo(0, 3); - editor.insert("juhu"); + win.navigateTo(0, 3); + win.insert("juhu"); - editor.navigateDown(); - assert.position(editor.getCursorPosition(), 1, 7); + win.navigateDown(); + assert.position(win.getCursorPosition(), 1, 7); } }; diff --git a/ace/model/window.js b/ace/model/window.js index 2c4bbbd3..4728d507 100644 --- a/ace/model/window.js +++ b/ace/model/window.js @@ -390,7 +390,6 @@ var Window = exports.Window = function(theme, search) { this._blockScrolling += 1; this.moveCursorTo(lineNumber-1, column || 0); this._blockScrolling -= 1; - if (!this.isRowVisible(this.getCursorPosition().row)) this.scrollToLine(lineNumber, true); }; @@ -400,6 +399,76 @@ var Window = exports.Window = function(theme, search) { this.moveCursorTo(row, column); }; + this.navigateUp = function(times) { + this.selection.clearSelection(); + times = times || 1; + this.selection.moveCursorBy(-times, 0); + }; + + this.navigateDown = function(times) { + this.selection.clearSelection(); + times = times || 1; + this.selection.moveCursorBy(times, 0); + }; + + this.navigateLeft = function(times) { + if (!this.selection.isEmpty()) { + var selectionStart = this.getSelectionRange().start; + this.moveCursorToPosition(selectionStart); + } + else { + times = times || 1; + while (times--) { + this.selection.moveCursorLeft(); + } + } + this.clearSelection(); + }; + + this.navigateRight = function(times) { + if (!this.selection.isEmpty()) { + var selectionEnd = this.getSelectionRange().end; + this.moveCursorToPosition(selectionEnd); + } + else { + times = times || 1; + while (times--) { + this.selection.moveCursorRight(); + } + } + this.clearSelection(); + }; + + this.navigateLineStart = function() { + this.selection.moveCursorLineStart(); + this.clearSelection(); + }; + + this.navigateLineEnd = function() { + this.selection.moveCursorLineEnd(); + this.clearSelection(); + }; + + this.navigateFileEnd = function() { + this.selection.moveCursorFileEnd(); + this.clearSelection(); + }; + + this.navigateFileStart = function() { + this.selection.moveCursorFileStart(); + this.clearSelection(); + }; + + this.navigateWordRight = function() { + this.selection.moveCursorWordRight(); + this.clearSelection(); + }; + + this.navigateWordLeft = function() { + this.selection.moveCursorWordLeft(); + this.clearSelection(); + }; + // SCROLLING this.scrollToY = function(scrollTop) { @@ -458,7 +527,7 @@ var Window = exports.Window = function(theme, search) { this.scrollToY(offset); }; - this.scrollCursorIntoView = function() { + this.scrollCursorIntoView = function() { // the editor is not visible if (this.size.scrollerHeight === 0) return; @@ -471,18 +540,16 @@ var Window = exports.Window = function(theme, search) { var left = pos.left; var top = pos.top; - if (this.scrollTop > top) { + if (this.scrollTop > top) this.scrollToY(top); - } if (this.scrollTop + this.size.scrollerHeight < top + this.charSize.height) this.scrollToY(top + this.charSize.height - this.size.scrollerHeight); var scrollLeft = this.scrollLeft; - if (scrollLeft > left) { + if (scrollLeft > left) this.scrollToX(left); - } if (scrollLeft + this.size.scrollerWidth < left + this.charSize.width) this.scrollToX(Math.round(left + this.charSize.width - this.size.scrollerWidth));