diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index f0a02183..48885e51 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -1,4 +1,5 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* vim:ts=4:sts=4:sw=4: + * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -70,6 +71,9 @@ var Anchor = exports.Anchor = function(doc, row, column) { this.onChange = function(e) { var delta = e.data; + if (delta.isMeta) + return; + var range = delta.range; if (range.start.row == range.end.row && range.start.row != this.row) diff --git a/lib/ace/document.js b/lib/ace/document.js index 3fd06c53..51f848ca 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -1,4 +1,5 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* vim:ts=4:sts=4:sw=4: + * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -20,6 +21,7 @@ * * Contributor(s): * Fabian Jakobs + * Mihai Sucan * * 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 @@ -363,9 +365,59 @@ var Document = function(text) { return end; }; + /** + * Move a range of text from the given range to the given position. + * + * @param fromRange {Range} The range of text you want moved within the + * document. + * @param toPosition {Object} The location (row and column) where you want + * to move the text to. + * @return {Range} The new range where the text was moved to. + */ + this.move = function(fromRange, toPosition) { + var text = this.getTextRange(fromRange); + this.remove(fromRange); + + var toRow = toPosition.row; + var toColumn = toPosition.column; + + // Make sure to update the insert location, when text is removed in + // front of the chosen point of insertion. + if (!fromRange.isMultiLine() && fromRange.start.row == toRow && + fromRange.end.column < toColumn) + toColumn -= text.length; + + if (fromRange.isMultiLine() && fromRange.end.row < toRow) { + var lines = this.$split(text); + toRow -= lines.length - 1; + } + + var endRow = toRow + fromRange.end.row - fromRange.start.row; + var endColumn = fromRange.isMultiLine() ? + fromRange.end.column : + toColumn + fromRange.end.column - fromRange.start.column; + + var toRange = new Range(toRow, toColumn, endRow, endColumn); + + this.insert(toRange.start, text); + + var delta = { + action: "move", + fromRange: fromRange, + toRange: toRange, + isMeta: true, + }; + this._dispatchEvent("change", { data: delta }); + + return toRange; + }; + this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { var delta = deltas[i]; + if (delta.isMeta) + continue; + var range = Range.fromPoints(delta.range.start, delta.range.end); if (delta.action == "insertLines") diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index b5d234ff..a09cc018 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -21,6 +21,7 @@ * * Contributor(s): * Fabian Jakobs + * Mihai Sucan * * 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 @@ -587,7 +588,7 @@ var EditSession = function(text, mode) { action.start = delta.range.start; } } - + // update selection based on last operation this.selection.clearSelection(); var action = actions[actions.length-1]; @@ -659,12 +660,6 @@ var EditSession = function(text, mode) { return addedRows; }; - this.moveText = function(range, toPosition) { - var removed = this.getTextRange(range); - this.doc.remove(range); - this.doc.insert(toPosition, removed); - }; - this.$clipRowToDocument = function(row) { return Math.max(0, Math.min(row, this.doc.getLength()-1)); }; @@ -756,7 +751,7 @@ var EditSession = function(text, mode) { }; this.$updateWrapDataOnChange = function(e) { - if (!this.$useWrapMode) { + if (!this.$useWrapMode || e.data.isMeta) { return; } diff --git a/lib/ace/editor.js b/lib/ace/editor.js index bc3a5aec..3dfc6c83 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -271,6 +271,9 @@ var Editor =function(renderer, session) { this.onDocumentChange = function(e) { var delta = e.data; + if (delta.isMeta) + return; + var range = delta.range; this.bgTokenizer.start(range.start.row); @@ -764,9 +767,9 @@ var Editor =function(renderer, session) { this.moveText = function(range, toPosition) { if (this.$readOnly) - return; + return null; - this.session.moveText(range, toPosition); + return this.session.doc.move(range, toPosition); }; this.copyLinesUp = function() { diff --git a/lib/ace/mode/javascript.js b/lib/ace/mode/javascript.js index a7634bf6..95e2f93f 100644 --- a/lib/ace/mode/javascript.js +++ b/lib/ace/mode/javascript.js @@ -1,4 +1,5 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* vim:ts=4:sts=4:sw=4: + * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -128,6 +129,9 @@ oop.inherits(Mode, TextMode); worker.call("setValue", [doc.getValue()]); doc.on("change", function(e) { + if (e.data.isMeta) + return; + e.range = { start: e.data.range.start, end: e.data.range.end diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 72f6c5f5..138f2462 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -21,6 +21,7 @@ * * Contributor(s): * Fabian Jakobs + * Mihai Sucan * * 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 @@ -39,7 +40,6 @@ define(function(require, exports, module) { var event = require("pilot/event"); -var Range = require("ace/range").Range; var MouseHandler = function(editor) { this.editor = editor; @@ -68,31 +68,40 @@ var MouseHandler = function(editor) { this.getScrollSpeed = function() { return this.$scrollSpeed; }; - + + this.$getEventPosition = function(e) { + var pageX = event.getDocumentX(e); + var pageY = event.getDocumentY(e); + var pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY); + pos.row = Math.max(0, Math.min(pos.row, this.editor.session.getLength()-1)); + return pos; + }; + this.onMouseDown = function(e) { var pageX = event.getDocumentX(e); var pageY = event.getDocumentY(e); + var pos = this.$getEventPosition(e); var editor = this.editor; - - var pos = editor.renderer.screenToTextCoordinates(pageX, pageY); - pos.row = Math.max(0, Math.min(pos.row, editor.session.getLength()-1)); - + var selectionRange = editor.getSelectionRange(); + var selectionEmpty = selectionRange.isEmpty(); var inSelection = false; var button = event.getButton(e) if (button != 0) { - var isEmpty = editor.selection.isEmpty() - if (isEmpty) { + if (selectionEmpty) { editor.moveCursorToPosition(pos); } if(button == 2) { - editor.textInput.onContextMenu({x: pageX, y: pageY}, isEmpty); + editor.textInput.onContextMenu({x: pageX, y: pageY}, selectionEmpty); event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose); } return; } else - inSelection = editor.getSelectionRange().contains(pos.row, pos.column); - + inSelection = !this.$clickSelection && + !editor.getReadOnly() && + !selectionEmpty && + selectionRange.contains(pos.row, pos.column); + if (!inSelection) { if (e.shiftKey) editor.selection.selectToPosition(pos) @@ -107,6 +116,8 @@ var MouseHandler = function(editor) { var self = this; var mousePageX, mousePageY; + var overwrite = editor.getOverwrite(); + var dragCursor = null; var onMouseSelection = function(e) { mousePageX = event.getDocumentX(e); @@ -120,16 +131,28 @@ var MouseHandler = function(editor) { var onMouseDragSelectionEnd = function() { clearInterval(timerId); + if (!self.$clickSelection) { + self.$clickSelection = null; + if (!dragCursor) { + editor.moveCursorToPosition(pos); + editor.selection.clearSelection(pos.row, pos.column); + } + } + + if (!dragCursor) + return; - var cursor = editor.getCursorPosition(); var selection = editor.getSelectionRange(); - editor.moveText(selection, cursor); + if (selection.contains(dragCursor.row, dragCursor.column)) + return; - var rows = selection.end.row - selection.start.row; - var columns = selection.end.column - selection.end.column; + editor.clearSelection(); + var newRange = editor.moveText(selection, dragCursor); + if (!newRange) + return; - var newSelection = new Range(cursor.row, cursor.column, cursor.row + rows, cursor.column + columns); - editor.selection.setSelectionRange(newSelection); + editor.selection.setSelectionRange(newRange); + dragCursor = null; }; var onSelectionInterval = function() { @@ -163,10 +186,11 @@ var MouseHandler = function(editor) { if (mousePageX === undefined || mousePageY === undefined) return; - var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); - cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); - - editor.moveCursorToPosition(cursor); + dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); + dragCursor.row = Math.max(0, Math.min(dragCursor.row, + editor.session.getLength() - 1)); + + editor.renderer.updateCursor(dragCursor, overwrite); editor.renderer.scrollCursorIntoView(); }; @@ -182,11 +206,15 @@ var MouseHandler = function(editor) { }; this.onMouseDoubleClick = function(e) { + var pos = this.$getEventPosition(e); + this.editor.moveCursorToPosition(pos); this.editor.selection.selectWord(); this.$clickSelection = this.editor.getSelectionRange(); }; this.onMouseTripleClick = function(e) { + var pos = this.$getEventPosition(e); + this.editor.moveCursorToPosition(pos); this.editor.selection.selectLine(); this.$clickSelection = this.editor.getSelectionRange(); };