From f79e4a3111088fc9957ebfbc66cc53ade9ab137b Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Mon, 14 Feb 2011 23:31:51 +0200 Subject: [PATCH 1/7] Started work on fixing issue 42. Code's not working as desired, yet. Work in progress. :) --- lib/ace/edit_session.js | 9 +++++- lib/ace/editor.js | 7 +++++ lib/ace/mouse_handler.js | 59 ++++++++++++++++++++++++++++++++-------- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index d8cb4e30..b5d234ff 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.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 @@ -658,6 +659,12 @@ 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)); }; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 676fe8ff..bc3a5aec 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -762,6 +762,13 @@ var Editor =function(renderer, session) { }); }; + this.moveText = function(range, toPosition) { + if (this.$readOnly) + return; + + this.session.moveText(range, toPosition); + }; + this.copyLinesUp = function() { if (this.$readOnly) return; diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index b3a16833..72f6c5f5 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.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 @@ -38,6 +39,7 @@ define(function(require, exports, module) { var event = require("pilot/event"); +var Range = require("ace/range").Range; var MouseHandler = function(editor) { this.editor = editor; @@ -74,6 +76,8 @@ var MouseHandler = function(editor) { var pos = editor.renderer.screenToTextCoordinates(pageX, pageY); pos.row = Math.max(0, Math.min(pos.row, editor.session.getLength()-1)); + + var inSelection = false; var button = event.getButton(e) if (button != 0) { @@ -86,16 +90,19 @@ var MouseHandler = function(editor) { event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose); } return; - } + } else + inSelection = editor.getSelectionRange().contains(pos.row, pos.column); - if (e.shiftKey) - editor.selection.selectToPosition(pos) - else { - editor.moveCursorToPosition(pos); - if (!editor.$clickSelection) - editor.selection.clearSelection(pos.row, pos.column); + if (!inSelection) { + if (e.shiftKey) + editor.selection.selectToPosition(pos) + else { + editor.moveCursorToPosition(pos); + if (!editor.$clickSelection) + editor.selection.clearSelection(pos.row, pos.column); + } } - + editor.renderer.scrollCursorIntoView(); var self = this; @@ -110,6 +117,20 @@ var MouseHandler = function(editor) { clearInterval(timerId); self.$clickSelection = null; }; + + var onMouseDragSelectionEnd = function() { + clearInterval(timerId); + + var cursor = editor.getCursorPosition(); + var selection = editor.getSelectionRange(); + editor.moveText(selection, cursor); + + var rows = selection.end.row - selection.start.row; + var columns = selection.end.column - selection.end.column; + + var newSelection = new Range(cursor.row, cursor.column, cursor.row + rows, cursor.column + columns); + editor.selection.setSelectionRange(newSelection); + }; var onSelectionInterval = function() { if (mousePageX === undefined || mousePageY === undefined) @@ -137,9 +158,25 @@ var MouseHandler = function(editor) { editor.renderer.scrollCursorIntoView(); }; + + var onDragSelectionInterval = function() { + if (mousePageX === undefined || mousePageY === undefined) + return; - event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); - var timerId = setInterval(onSelectionInterval, 20); + var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); + cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); + + editor.moveCursorToPosition(cursor); + editor.renderer.scrollCursorIntoView(); + }; + + if (inSelection) { + event.capture(editor.container, onMouseSelection, onMouseDragSelectionEnd); + var timerId = setInterval(onDragSelectionInterval, 20); + } else { + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(onSelectionInterval, 20); + } return event.preventDefault(e); }; From 3f24b7a55356546def9101db8ef05c2b57345613 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Tue, 15 Feb 2011 19:25:53 +0200 Subject: [PATCH 2/7] Completed work. Selected text is now draggable. --- lib/ace/anchor.js | 6 +++- lib/ace/document.js | 57 ++++++++++++++++++++++++++++++- lib/ace/edit_session.js | 11 ++---- lib/ace/editor.js | 7 ++-- lib/ace/mode/javascript.js | 6 +++- lib/ace/mouse_handler.js | 70 ++++++++++++++++++++++++++------------ 6 files changed, 123 insertions(+), 34 deletions(-) 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(); }; From 471188c6690ed54c1daac9d59d6d12111d37b4b7 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Wed, 16 Feb 2011 13:03:08 +0200 Subject: [PATCH 3/7] selection must be draggable after triple click as well --- lib/ace/mouse_handler.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 138f2462..bfcff6f1 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -97,8 +97,7 @@ var MouseHandler = function(editor) { } return; } else - inSelection = !this.$clickSelection && - !editor.getReadOnly() && + inSelection = !editor.getReadOnly() && !selectionEmpty && selectionRange.contains(pos.row, pos.column); From 44846b4983338cca2cb6f766d3a14b93fc74ea6d Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Fri, 18 Feb 2011 14:53:44 +0200 Subject: [PATCH 4/7] rebased the branch, moved the moveText() from Document to EditSession, and removed the 'move' change event, which is no longer needed given the fixes in UndoManager. --- lib/ace/anchor.js | 6 +--- lib/ace/document.js | 57 +------------------------------------- lib/ace/edit_session.js | 41 ++++++++++++++++++++++++++- lib/ace/editor.js | 5 +--- lib/ace/mode/javascript.js | 6 +--- 5 files changed, 44 insertions(+), 71 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 48885e51..f0a02183 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -1,5 +1,4 @@ -/* vim:ts=4:sts=4:sw=4: - * ***** BEGIN LICENSE BLOCK ***** +/* ***** 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 @@ -71,9 +70,6 @@ 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 51f848ca..3fd06c53 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -1,5 +1,4 @@ -/* vim:ts=4:sts=4:sw=4: - * ***** BEGIN LICENSE BLOCK ***** +/* ***** 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 @@ -21,7 +20,6 @@ * * 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 @@ -365,59 +363,9 @@ 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 a09cc018..91b219ec 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -602,6 +602,45 @@ var EditSession = function(text, mode) { return this.doc.replace(range, text); }; + /** + * 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.moveText = 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.doc.$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); + + return toRange; + }; + this.indentRows = function(startRow, endRow, indentString) { indentString = indentString.replace(/\t/g, this.getTabString()); for (var row=startRow; row<=endRow; row++) { @@ -751,7 +790,7 @@ var EditSession = function(text, mode) { }; this.$updateWrapDataOnChange = function(e) { - if (!this.$useWrapMode || e.data.isMeta) { + if (!this.$useWrapMode) { return; } diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 3dfc6c83..974ae509 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -271,9 +271,6 @@ 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); @@ -769,7 +766,7 @@ var Editor =function(renderer, session) { if (this.$readOnly) return null; - return this.session.doc.move(range, toPosition); + return this.session.moveText(range, toPosition); }; this.copyLinesUp = function() { diff --git a/lib/ace/mode/javascript.js b/lib/ace/mode/javascript.js index 95e2f93f..a7634bf6 100644 --- a/lib/ace/mode/javascript.js +++ b/lib/ace/mode/javascript.js @@ -1,5 +1,4 @@ -/* vim:ts=4:sts=4:sw=4: - * ***** BEGIN LICENSE BLOCK ***** +/* ***** 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 @@ -129,9 +128,6 @@ 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 From c6b4fc93f2791e95be5796bff524836fdd057dac Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Fri, 18 Feb 2011 19:56:08 +0200 Subject: [PATCH 5/7] added hold-mousedown delay to enable selection drag --- lib/ace/css/editor.css | 4 +++ lib/ace/mouse_handler.js | 67 +++++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index 6526d0fd..06bc87b9 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -152,3 +152,7 @@ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } + +.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer { + cursor: move; +} diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index bfcff6f1..848fab9d 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -40,6 +40,14 @@ define(function(require, exports, module) { var event = require("pilot/event"); +var dom = require("pilot/dom"); + +const STATE_UNKNOWN = 0; +const STATE_SELECT = 1; +const STATE_DRAG = 2; + +const DRAG_TIMER = 500; // milliseconds +const DRAG_OFFSET = 5; // pixels var MouseHandler = function(editor) { this.editor = editor; @@ -77,6 +85,10 @@ var MouseHandler = function(editor) { return pos; }; + this.$distance = function(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); + }; + this.onMouseDown = function(e) { var pageX = event.getDocumentX(e); var pageY = event.getDocumentY(e); @@ -84,6 +96,7 @@ var MouseHandler = function(editor) { var editor = this.editor; var selectionRange = editor.getSelectionRange(); var selectionEmpty = selectionRange.isEmpty(); + var state = STATE_UNKNOWN; var inSelection = false; var button = event.getButton(e) @@ -109,6 +122,10 @@ var MouseHandler = function(editor) { if (!editor.$clickSelection) editor.selection.clearSelection(pos.row, pos.column); } + + // Directly pick STATE_SELECT, since the user is not clicking inside + // a selection. + state = STATE_SELECT; } editor.renderer.scrollCursorIntoView(); @@ -117,6 +134,7 @@ var MouseHandler = function(editor) { var mousePageX, mousePageY; var overwrite = editor.getOverwrite(); var dragCursor = null; + var mousedownTime = (new Date()).getTime(); var onMouseSelection = function(e) { mousePageX = event.getDocumentX(e); @@ -125,11 +143,17 @@ var MouseHandler = function(editor) { var onMouseSelectionEnd = function() { clearInterval(timerId); - self.$clickSelection = null; + if (state == STATE_DRAG) + onMouseDragSelectionEnd(); + else + self.$clickSelection = null; + + state = STATE_UNKNOWN; }; var onMouseDragSelectionEnd = function() { - clearInterval(timerId); + dom.removeCssClass(editor.container, "ace_dragging"); + if (!self.$clickSelection) { self.$clickSelection = null; if (!dragCursor) { @@ -142,22 +166,43 @@ var MouseHandler = function(editor) { return; var selection = editor.getSelectionRange(); - if (selection.contains(dragCursor.row, dragCursor.column)) + if (selection.contains(dragCursor.row, dragCursor.column)) { + dragCursor = null; return; + } editor.clearSelection(); var newRange = editor.moveText(selection, dragCursor); - if (!newRange) + if (!newRange) { + dragCursor = null; return; + } editor.selection.setSelectionRange(newRange); - dragCursor = null; }; var onSelectionInterval = function() { if (mousePageX === undefined || mousePageY === undefined) return; + + if (state == STATE_UNKNOWN) { + var distance = self.$distance(pageX, pageY, mousePageX, mousePageY); + var time = (new Date()).getTime(); + + if (distance > DRAG_OFFSET) + state = STATE_SELECT; + else if ((time - mousedownTime) > DRAG_TIMER) { + state = STATE_DRAG; + dom.addCssClass(editor.container, "ace_dragging"); + } + + } else if (state == STATE_DRAG) + onDragSelectionInterval(); + else if (state == STATE_SELECT) + onUpdateSelectionInterval(); + }; + var onUpdateSelectionInterval = function() { var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); @@ -182,9 +227,6 @@ var MouseHandler = function(editor) { }; var onDragSelectionInterval = function() { - if (mousePageX === undefined || mousePageY === undefined) - return; - dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); dragCursor.row = Math.max(0, Math.min(dragCursor.row, editor.session.getLength() - 1)); @@ -193,13 +235,8 @@ var MouseHandler = function(editor) { editor.renderer.scrollCursorIntoView(); }; - if (inSelection) { - event.capture(editor.container, onMouseSelection, onMouseDragSelectionEnd); - var timerId = setInterval(onDragSelectionInterval, 20); - } else { - event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); - var timerId = setInterval(onSelectionInterval, 20); - } + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(onSelectionInterval, 20); return event.preventDefault(e); }; From 389d33acac3be30bb50bafb36b197d4456b23837 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sat, 19 Feb 2011 11:20:47 +0100 Subject: [PATCH 6/7] some more mouse handler fixes --- lib/ace/mouse_handler.js | 47 +++++++++++++++++++++++++--------------- support/pilot | 2 +- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 848fab9d..e3e74527 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -42,12 +42,12 @@ define(function(require, exports, module) { var event = require("pilot/event"); var dom = require("pilot/dom"); -const STATE_UNKNOWN = 0; -const STATE_SELECT = 1; -const STATE_DRAG = 2; +var STATE_UNKNOWN = 0; +var STATE_SELECT = 1; +var STATE_DRAG = 2; -const DRAG_TIMER = 500; // milliseconds -const DRAG_OFFSET = 5; // pixels +var DRAG_TIMER = 250; // milliseconds +var DRAG_OFFSET = 5; // pixels var MouseHandler = function(editor) { this.editor = editor; @@ -115,17 +115,9 @@ var MouseHandler = function(editor) { selectionRange.contains(pos.row, pos.column); if (!inSelection) { - if (e.shiftKey) - editor.selection.selectToPosition(pos) - else { - editor.moveCursorToPosition(pos); - if (!editor.$clickSelection) - editor.selection.clearSelection(pos.row, pos.column); - } - // Directly pick STATE_SELECT, since the user is not clicking inside // a selection. - state = STATE_SELECT; + onStartSelect(pos); } editor.renderer.scrollCursorIntoView(); @@ -143,7 +135,9 @@ var MouseHandler = function(editor) { var onMouseSelectionEnd = function() { clearInterval(timerId); - if (state == STATE_DRAG) + if (state == STATE_UNKNOWN) { + onStartSelect(pos); + } else if (state == STATE_DRAG) onMouseDragSelectionEnd(); else self.$clickSelection = null; @@ -189,19 +183,36 @@ var MouseHandler = function(editor) { var distance = self.$distance(pageX, pageY, mousePageX, mousePageY); var time = (new Date()).getTime(); - if (distance > DRAG_OFFSET) + + if (distance > DRAG_OFFSET) { state = STATE_SELECT; - else if ((time - mousedownTime) > DRAG_TIMER) { + var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); + cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); + onStartSelect(cursor); + } else if ((time - mousedownTime) > DRAG_TIMER) { state = STATE_DRAG; dom.addCssClass(editor.container, "ace_dragging"); } - } else if (state == STATE_DRAG) + } + + if (state == STATE_DRAG) onDragSelectionInterval(); else if (state == STATE_SELECT) onUpdateSelectionInterval(); }; + function onStartSelect(pos) { + if (e.shiftKey) + editor.selection.selectToPosition(pos) + else { + editor.moveCursorToPosition(pos); + if (!editor.$clickSelection) + editor.selection.clearSelection(pos.row, pos.column); + } + state = STATE_SELECT; + } + var onUpdateSelectionInterval = function() { var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); diff --git a/support/pilot b/support/pilot index 6e1fbe1d..cbfac498 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit 6e1fbe1dfdff64020f15cd9e23ea72b7803cf406 +Subproject commit cbfac498d30d43fdb7687d198c5b752736222c2f From 387e28202969541b93e73e52c277d92691c423a1 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Sun, 20 Feb 2011 13:18:27 +0100 Subject: [PATCH 7/7] fix triple click --- lib/ace/mouse_handler.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index e3e74527..c17b47a7 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -94,6 +94,7 @@ var MouseHandler = function(editor) { var pageY = event.getDocumentY(e); var pos = this.$getEventPosition(e); var editor = this.editor; + var self = this; var selectionRange = editor.getSelectionRange(); var selectionEmpty = selectionRange.isEmpty(); var state = STATE_UNKNOWN; @@ -122,7 +123,6 @@ var MouseHandler = function(editor) { editor.renderer.scrollCursorIntoView(); - var self = this; var mousePageX, mousePageY; var overwrite = editor.getOverwrite(); var dragCursor = null; @@ -135,13 +135,12 @@ var MouseHandler = function(editor) { var onMouseSelectionEnd = function() { clearInterval(timerId); - if (state == STATE_UNKNOWN) { + if (state == STATE_UNKNOWN) onStartSelect(pos); - } else if (state == STATE_DRAG) + else if (state == STATE_DRAG) onMouseDragSelectionEnd(); - else - self.$clickSelection = null; - + + self.$clickSelection = null; state = STATE_UNKNOWN; }; @@ -149,7 +148,6 @@ var MouseHandler = function(editor) { dom.removeCssClass(editor.container, "ace_dragging"); if (!self.$clickSelection) { - self.$clickSelection = null; if (!dragCursor) { editor.moveCursorToPosition(pos); editor.selection.clearSelection(pos.row, pos.column); @@ -206,9 +204,10 @@ var MouseHandler = function(editor) { if (e.shiftKey) editor.selection.selectToPosition(pos) else { - editor.moveCursorToPosition(pos); - if (!editor.$clickSelection) + if (!self.$clickSelection) { + editor.moveCursorToPosition(pos); editor.selection.clearSelection(pos.row, pos.column); + } } state = STATE_SELECT; } @@ -217,7 +216,7 @@ var MouseHandler = function(editor) { var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY); cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1)); - if (self.$clickSelection) { + if (self.$clickSelection) { if (self.$clickSelection.contains(cursor.row, cursor.column)) { editor.selection.setSelectionRange(self.$clickSelection); } else {