From f1d25fb7b2d13ea87ce9075b1415f29089b08bbd Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Wed, 7 Apr 2010 10:08:44 +0200 Subject: [PATCH] add support for drag selection --- Editor.js | 111 +++++++++++++++++++++++++++++++-------------- VirtualRenderer.js | 13 +----- lib.js | 23 ++++++++++ 3 files changed, 103 insertions(+), 44 deletions(-) diff --git a/Editor.js b/Editor.js index a26bbab7..14e2c744 100644 --- a/Editor.js +++ b/Editor.js @@ -174,14 +174,14 @@ function KeyBinding(element, host) } return stopEvent(e); - case keys.DELETE: - host.clearSelection(); + case keys.DELETE: host.removeRight(); + host.clearSelection(); return stopEvent(e); - case keys.BACKSPACE: - host.clearSelection(); + case keys.BACKSPACE: host.removeLeft(); + host.clearSelection(); return stopEvent(e); case keys.TAB: @@ -196,7 +196,7 @@ function Editor(doc, renderer) var container = renderer.getContainerElement(); this.renderer = renderer; - var textInput = new TextInput(container, this); + this.textInput = new TextInput(container, this); new KeyBinding(container, this); addListener(container, "mousedown", bind(this.onMouseDown, this)); @@ -247,14 +247,41 @@ Editor.prototype = { this.textInput.focus(); - var pos = this.renderer.screenToTextCoordinates(pageX, pageY); + var pos = this.renderer.screenToTextCoordinates(e.pageX, e.pageY); this.moveTo(pos.row, pos.column); this.setSelectionAnchor(pos.row, pos.column); - this.renderer.scrollCursorIntoView(); + + var _self = this; + var mousePageX, mousePageY; + + var onMouseSelection = function(e) { + mousePageX = e.pageX; + mousePageY = e.pageY; + }; + + var onMouseSelectionEnd = function() { + clearInterval(timerId); + }; + + var onSelectionInterval = function() + { + if (mousePageX === undefined || mousePageY === undefined) return; + + selectionLead = _self.renderer.screenToTextCoordinates(mousePageX, mousePageY); + + _self._moveSelection(function() { + _self.moveTo(selectionLead.row, selectionLead.column); + }); + _self.renderer.scrollCursorIntoView(); + }; + + capture(this.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(onSelectionInterval, 100); + return preventDefault(e); }, - + onMouseWheel : function(e) { var delta = e.wheelDeltaY; @@ -282,24 +309,35 @@ Editor.prototype = }, onTextInput: function(text) - { - this.cursor = this.doc.insert(this.cursor, text); - this.clearSelection(); + { + if (this.hasSelection()) + { + this.cursor = this.doc.remove(this.getSelectionRange()); + this.clearSelection(); + } + this.cursor = this.doc.insert(this.cursor, text); this.draw(); this.renderer.scrollCursorIntoView(); }, removeRight : function() - { - var rangeEnd = { - row: this.cursor.row, - column: this.cursor.column + 1 + { + if (this.hasSelection()) + { + this.cursor = this.doc.remove(this.getSelectionRange()); } - if (rangeEnd.column > this.doc.getLine(this.cursor.row).length) { - rangeEnd.row += 1; - rangeEnd.column = 0; + else + { + var rangeEnd = { + row: this.cursor.row, + column: this.cursor.column + 1 + } + if (rangeEnd.column > this.doc.getLine(this.cursor.row).length) { + rangeEnd.row += 1; + rangeEnd.column = 0; + } + this.doc.remove({start: this.cursor, end: renageEnd}); } - this.doc.remove({start: this.cursor, end: renageEnd}); this.draw(); this.renderer.scrollCursorIntoView(); @@ -307,20 +345,27 @@ Editor.prototype = removeLeft : function() { - if (this.cursor.row == 0 && this.cursor.column == 0) { - return; - } - - var rangeStart = { - row: this.cursor.row, - column: this.cursor.column + -1 - } - if (rangeStart.column < 0) + if (this.hasSelection()) { - rangeStart.row -= 1; - rangeStart.column = this.doc.getLine(this.cursor.row-1).length; + this.cursor = this.doc.remove(this.getSelectionRange()); + } + else + { + if (this.cursor.row == 0 && this.cursor.column == 0) { + return; + } + + var rangeStart = { + row: this.cursor.row, + column: this.cursor.column + -1 + } + if (rangeStart.column < 0) + { + rangeStart.row -= 1; + rangeStart.column = this.doc.getLine(this.cursor.row-1).length; + } + this.cursor = this.doc.remove({start: rangeStart, end: this.cursor}); } - this.cursor = this.doc.remove({start: rangeStart, end: this.cursor}); this.draw(); this.renderer.scrollCursorIntoView(); @@ -393,8 +438,8 @@ Editor.prototype = setSelectionAnchor : function(row, column) { this.selectionAnchor = { - row: row, - column: column + row: Math.min(this.doc.getLength()-1, Math.max(0, row)), + column: Math.min(this.doc.getLine(this.cursor.row).length, Math.max(0, column)) }; this.selectionLead = null; diff --git a/VirtualRenderer.js b/VirtualRenderer.js index 33e4a367..0bd1efa7 100644 --- a/VirtualRenderer.js +++ b/VirtualRenderer.js @@ -313,17 +313,8 @@ VirtualRenderer.prototype.screenToTextCoordinates = function(pageX, pageY) { var canvasPos = this.container.getBoundingClientRect(); - if (pageX < canvasPos.left || pageX > canvasPos.right) { - col = null; - } else { - var col = Math.floor((pageX + this.container.scrollLeft - canvasPos.left) / this.characterWidth); - } - - if (pageY < canvasPos.top || pageY > canvasPos.bottom) { - row = null; - } else { - var row = Math.floor((pageY + this.scrollTop - canvasPos.top) / this.lineHeight); - } + var col = Math.floor((pageX + this.container.scrollLeft - canvasPos.left) / this.characterWidth); + var row = Math.floor((pageY + this.scrollTop - canvasPos.top) / this.lineHeight); return { row: row, diff --git a/lib.js b/lib.js index 0f973453..981c559b 100644 --- a/lib.js +++ b/lib.js @@ -78,4 +78,27 @@ bind = function(fcn, context) { return function() { return fcn.apply(context, arguments); } +} + +capture = function(el, eventHandler, releaseCaptureHandler) +{ + function onMouseMove(e) + { + eventHandler(e); + e.stopPropagation(); + } + + function onMouseUp(e) + { + eventHandler && eventHandler(e); + releaseCaptureHandler && releaseCaptureHandler(); + + document.removeEventListener("mousemove", onMouseMove, true); + document.removeEventListener("mouseup", onMouseUp, true); + + e.stopPropagation(); + } + + document.addEventListener("mousemove", onMouseMove, true); + document.addEventListener("mouseup", onMouseUp, true); } \ No newline at end of file