commit
4c87594521
13 changed files with 423 additions and 313 deletions
|
|
@ -36,6 +36,12 @@
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ace_gutter_active_line {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.ace_gutter.horscroll {
|
.ace_gutter.horscroll {
|
||||||
box-shadow: 0px 0px 20px rgba(0,0,0,0.4);
|
box-shadow: 0px 0px 20px rgba(0,0,0,0.4);
|
||||||
}
|
}
|
||||||
|
|
@ -94,8 +100,8 @@
|
||||||
.ace_editor textarea {
|
.ace_editor textarea {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
width: 10px;
|
width: 0.5em;
|
||||||
height: 30px;
|
height: 1em;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ var Editor = function(renderer, session) {
|
||||||
|
|
||||||
this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
|
this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
|
||||||
this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
|
this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
|
||||||
|
this.renderer.textarea = this.textInput.getElement();
|
||||||
this.keyBinding = new KeyBinding(this);
|
this.keyBinding = new KeyBinding(this);
|
||||||
|
|
||||||
// TODO detect touch event support
|
// TODO detect touch event support
|
||||||
|
|
@ -385,11 +386,7 @@ var Editor = function(renderer, session) {
|
||||||
|
|
||||||
this.$cursorChange = function() {
|
this.$cursorChange = function() {
|
||||||
this.renderer.updateCursor();
|
this.renderer.updateCursor();
|
||||||
|
};
|
||||||
// move text input over the cursor
|
|
||||||
// this is required for iOS and IME
|
|
||||||
this.renderer.moveTextAreaToCursor(this.textInput.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor@onDocumentChange(e)
|
* Editor@onDocumentChange(e)
|
||||||
|
|
@ -458,7 +455,6 @@ var Editor = function(renderer, session) {
|
||||||
|
|
||||||
this.$highlightBrackets();
|
this.$highlightBrackets();
|
||||||
this.$updateHighlightActiveLine();
|
this.$updateHighlightActiveLine();
|
||||||
this.$updateHighlightGutterLine();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** internal, hide
|
/** internal, hide
|
||||||
|
|
@ -490,21 +486,6 @@ var Editor = function(renderer, session) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** internal, hide
|
|
||||||
* Editor.$updateHighlightGutterLine()
|
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
this.$updateHighlightGutterLine = function(){
|
|
||||||
if (typeof this.$lastrow == "number")
|
|
||||||
this.renderer.removeGutterDecoration(this.$lastrow, "ace_gutter_active_line");
|
|
||||||
|
|
||||||
this.$lastrow = null;
|
|
||||||
|
|
||||||
if (this.$highlightGutterLine)
|
|
||||||
this.renderer.addGutterDecoration(
|
|
||||||
this.$lastrow = this.getCursorPosition().row, "ace_gutter_active_line");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor@onSelectionChange(e)
|
* Editor@onSelectionChange(e)
|
||||||
|
|
@ -526,7 +507,6 @@ var Editor = function(renderer, session) {
|
||||||
session.$selectionMarker = session.addMarker(range, "ace_selection", style);
|
session.$selectionMarker = session.addMarker(range, "ace_selection", style);
|
||||||
} else {
|
} else {
|
||||||
this.$updateHighlightActiveLine();
|
this.$updateHighlightActiveLine();
|
||||||
this.$updateHighlightGutterLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$highlightSelectedWord)
|
if (this.$highlightSelectedWord)
|
||||||
|
|
@ -605,7 +585,6 @@ var Editor = function(renderer, session) {
|
||||||
// Update the active line marker as due to folding changes the current
|
// Update the active line marker as due to folding changes the current
|
||||||
// line range on the screen might have changed.
|
// line range on the screen might have changed.
|
||||||
this.$updateHighlightActiveLine();
|
this.$updateHighlightActiveLine();
|
||||||
this.$updateHighlightGutterLine();
|
|
||||||
// TODO: This might be too much updating. Okay for now.
|
// TODO: This might be too much updating. Okay for now.
|
||||||
this.renderer.updateFull();
|
this.renderer.updateFull();
|
||||||
};
|
};
|
||||||
|
|
@ -891,12 +870,11 @@ var Editor = function(renderer, session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$highlightGutterLine = true;
|
this.$highlightGutterLine = true;
|
||||||
this.setHighlightGutterLine = function(shouldHighlightGutterLine) {
|
this.setHighlightGutterLine = function(shouldHighlight) {
|
||||||
if (this.$highlightGutterLine == shouldHighlightGutterLine)
|
if (this.$highlightGutterLine == shouldHighlight)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.$highlightGutterLine = shouldHighlightGutterLine;
|
this.renderer.setHighlightGutterLine(shouldHighlight);
|
||||||
this.$updateHighlightGutterLine();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getHighlightGutterLine = function() {
|
this.getHighlightGutterLine = function() {
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ var TextInput = function(parentNode, host) {
|
||||||
if (useragent.isTouchPad)
|
if (useragent.isTouchPad)
|
||||||
text.setAttribute("x-palm-disable-auto-cap", true);
|
text.setAttribute("x-palm-disable-auto-cap", true);
|
||||||
|
|
||||||
|
text.setAttribute("wrap", "off");
|
||||||
|
|
||||||
text.style.left = "-10000px";
|
text.style.left = "-10000px";
|
||||||
text.style.position = "fixed";
|
text.style.position = "fixed";
|
||||||
parentNode.insertBefore(text, parentNode.firstChild);
|
parentNode.insertBefore(text, parentNode.firstChild);
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,9 @@ var Cursor = function(parentEl) {
|
||||||
if (overwrite != this.overwrite)
|
if (overwrite != this.overwrite)
|
||||||
this.$setOverite(overwrite);
|
this.$setOverite(overwrite);
|
||||||
|
|
||||||
|
// cache for textarea and gutter highlight
|
||||||
|
this.$pixelPos = pixelPos;
|
||||||
|
|
||||||
this.restartTimer();
|
this.restartTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,9 +395,9 @@ var Text = function(parentEl) {
|
||||||
if (a) {
|
if (a) {
|
||||||
return new Array(c.length+1).join(" ");
|
return new Array(c.length+1).join(" ");
|
||||||
} else if (c == "&") {
|
} else if (c == "&") {
|
||||||
return useragent.isOldGecko ? "&" : "&";
|
return "&";
|
||||||
} else if (c == "<") {
|
} else if (c == "<") {
|
||||||
return "<";
|
return "<";
|
||||||
} else if (c == "\t") {
|
} else if (c == "\t") {
|
||||||
var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
|
var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
|
||||||
screenColumn += tabSize - 1;
|
screenColumn += tabSize - 1;
|
||||||
|
|
@ -411,10 +411,7 @@ var Text = function(parentEl) {
|
||||||
(self.config.characterWidth * 2) +
|
(self.config.characterWidth * 2) +
|
||||||
"px'>" + space + "</span>";
|
"px'>" + space + "</span>";
|
||||||
} else if (b) {
|
} else if (b) {
|
||||||
if (self.showInvisibles)
|
return "<span class='ace_invisible ace_invalid'>" + self.SPACE_CHAR + "</span>";
|
||||||
return "<span class='ace_invisible ace_invalid'>" + self.SPACE_CHAR + "</span>";
|
|
||||||
else
|
|
||||||
return " ";
|
|
||||||
} else {
|
} else {
|
||||||
screenColumn += 1;
|
screenColumn += 1;
|
||||||
return "<span class='ace_cjk' style='width:" +
|
return "<span class='ace_cjk' style='width:" +
|
||||||
|
|
|
||||||
|
|
@ -87,22 +87,6 @@ exports.preventDefault = function(e) {
|
||||||
e.returnValue = false;
|
e.returnValue = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getDocumentX = function(e) {
|
|
||||||
if (e.clientX) {
|
|
||||||
return e.clientX + dom.getPageScrollLeft();
|
|
||||||
} else {
|
|
||||||
return e.pageX;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getDocumentY = function(e) {
|
|
||||||
if (e.clientY) {
|
|
||||||
return e.clientY + dom.getPageScrollTop();
|
|
||||||
} else {
|
|
||||||
return e.pageY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @return {Number} 0 for left button, 1 for middle button, 2 for right button
|
* @return {Number} 0 for left button, 1 for middle button, 2 for right button
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,24 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function GutterHandler(editor) {
|
function GutterHandler(mouseHandler) {
|
||||||
editor.setDefaultHandler("gutterclick", function(e) {
|
var editor = mouseHandler.editor;
|
||||||
|
|
||||||
|
mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
|
||||||
|
if (e.domEvent.target.className.indexOf("ace_gutter-cell") == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!editor.isFocused())
|
||||||
|
return;
|
||||||
|
|
||||||
var row = e.getDocumentPosition().row;
|
var row = e.getDocumentPosition().row;
|
||||||
var selection = editor.session.selection;
|
var selection = editor.session.selection;
|
||||||
|
|
||||||
selection.moveCursorTo(row, 0);
|
selection.moveCursorTo(row, 0);
|
||||||
selection.selectLine();
|
selection.selectLine();
|
||||||
|
|
||||||
|
mouseHandler.$clickSelection = selection.getRange();
|
||||||
|
mouseHandler.captureMouse(e, "selectByLines");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Fabian Jakobs <fabian AT ajax DOT org>
|
* Fabian Jakobs <fabian AT ajax DOT org>
|
||||||
* Mike de Boer <mike AT ajax DOT org>
|
* Mike de Boer <mike AT ajax DOT org>
|
||||||
|
* Harutyun Amirjanyan <harutyun AT c9 DOT io>
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|
@ -40,41 +41,48 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var event = require("../lib/event");
|
|
||||||
var dom = require("../lib/dom");
|
var dom = require("../lib/dom");
|
||||||
var BrowserFocus = require("../lib/browser_focus").BrowserFocus;
|
var BrowserFocus = require("../lib/browser_focus").BrowserFocus;
|
||||||
|
|
||||||
var STATE_UNKNOWN = 0;
|
|
||||||
var STATE_SELECT = 1;
|
|
||||||
var STATE_DRAG = 2;
|
|
||||||
|
|
||||||
var DRAG_OFFSET = 5; // pixels
|
var DRAG_OFFSET = 5; // pixels
|
||||||
|
|
||||||
function DefaultHandlers(editor) {
|
|
||||||
this.editor = editor;
|
|
||||||
this.$clickSelection = null;
|
|
||||||
this.browserFocus = new BrowserFocus();
|
|
||||||
|
|
||||||
editor.setDefaultHandler("mousedown", this.onMouseDown.bind(this));
|
|
||||||
editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(this));
|
function DefaultHandlers(mouseHandler) {
|
||||||
editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(this));
|
mouseHandler.$clickSelection = null;
|
||||||
editor.setDefaultHandler("quadclick", this.onQuadClick.bind(this));
|
mouseHandler.browserFocus = new BrowserFocus();
|
||||||
editor.setDefaultHandler("mousewheel", this.onScroll.bind(this));
|
|
||||||
|
var editor = mouseHandler.editor;
|
||||||
|
editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler));
|
||||||
|
editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler));
|
||||||
|
editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler));
|
||||||
|
editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler));
|
||||||
|
editor.setDefaultHandler("mousewheel", this.onScroll.bind(mouseHandler));
|
||||||
|
|
||||||
|
var exports = ["select", "startSelect", "drag", "dragEnd", "dragWait",
|
||||||
|
"dragWaitEnd", "startDrag"];
|
||||||
|
|
||||||
|
exports.forEach(function(x) {
|
||||||
|
mouseHandler[x] = this[x];
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
|
||||||
|
mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange");
|
||||||
}
|
}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
this.onMouseDown = function(ev) {
|
this.onMouseDown = function(ev) {
|
||||||
|
this.mousedownEvent = ev;
|
||||||
var inSelection = ev.inSelection();
|
var inSelection = ev.inSelection();
|
||||||
var pageX = ev.pageX;
|
|
||||||
var pageY = ev.pageY;
|
|
||||||
var pos = ev.getDocumentPosition();
|
var pos = ev.getDocumentPosition();
|
||||||
var editor = this.editor;
|
var editor = this.editor;
|
||||||
var _self = this;
|
var _self = this;
|
||||||
|
|
||||||
|
this.ev = ev
|
||||||
var selectionRange = editor.getSelectionRange();
|
var selectionRange = editor.getSelectionRange();
|
||||||
var selectionEmpty = selectionRange.isEmpty();
|
var selectionEmpty = selectionRange.isEmpty();
|
||||||
var state = STATE_UNKNOWN;
|
|
||||||
|
|
||||||
var button = ev.getButton();
|
var button = ev.getButton();
|
||||||
if (button !== 0) {
|
if (button !== 0) {
|
||||||
|
|
@ -82,167 +90,192 @@ function DefaultHandlers(editor) {
|
||||||
editor.moveCursorToPosition(pos);
|
editor.moveCursorToPosition(pos);
|
||||||
editor.selection.clearSelection();
|
editor.selection.clearSelection();
|
||||||
}
|
}
|
||||||
if (button == 2) {
|
// 2: contextmenu, 1: linux paste
|
||||||
editor.textInput.onContextMenu({x: ev.clientX, y: ev.clientY}, selectionEmpty);
|
this.moveTextarea = function() {
|
||||||
event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
|
editor.textInput.onContextMenu({x: _self.x, y: _self.y});
|
||||||
}
|
};
|
||||||
|
this.moveTextareaEnd = editor.textInput.onContextMenuClose;
|
||||||
|
|
||||||
|
editor.textInput.onContextMenu({x: this.x, y: this.y}, selectionEmpty);
|
||||||
|
this.captureMouse(ev, "moveTextarea");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this click caused the editor to be focused should not clear the
|
// if this click caused the editor to be focused should not clear the
|
||||||
// selection
|
// selection
|
||||||
if (
|
if (inSelection && !editor.isFocused()) {
|
||||||
inSelection && (
|
|
||||||
!this.browserFocus.isFocused()
|
|
||||||
|| new Date().getTime() - this.browserFocus.lastFocus < 20
|
|
||||||
|| !editor.isFocused()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
editor.focus();
|
editor.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inSelection) {
|
if (!inSelection || this.$clickSelection || ev.getShiftKey()) {
|
||||||
// Directly pick STATE_SELECT, since the user is not clicking inside
|
// Directly pick STATE_SELECT, since the user is not clicking inside
|
||||||
// a selection.
|
// a selection.
|
||||||
onStartSelect(pos);
|
this.startSelect(pos);
|
||||||
}
|
} else if (inSelection) {
|
||||||
|
var e = ev.domEvent;
|
||||||
var mousePageX = pageX, mousePageY = pageY;
|
if ((e.ctrlKey || e.altKey)) {
|
||||||
var mousedownTime = (new Date()).getTime();
|
this.startDrag();
|
||||||
var dragCursor, dragRange, dragSelectionMarker;
|
|
||||||
|
|
||||||
var onMouseSelection = function(e) {
|
|
||||||
mousePageX = event.getDocumentX(e);
|
|
||||||
mousePageY = event.getDocumentY(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onMouseSelectionEnd = function(e) {
|
|
||||||
clearInterval(timerId);
|
|
||||||
if (state == STATE_UNKNOWN)
|
|
||||||
onStartSelect(pos);
|
|
||||||
else if (state == STATE_DRAG)
|
|
||||||
onMouseDragSelectionEnd(e);
|
|
||||||
|
|
||||||
_self.$clickSelection = null;
|
|
||||||
state = STATE_UNKNOWN;
|
|
||||||
};
|
|
||||||
|
|
||||||
var onMouseDragSelectionEnd = function(e) {
|
|
||||||
dom.removeCssClass(editor.container, "ace_dragging");
|
|
||||||
editor.session.removeMarker(dragSelectionMarker);
|
|
||||||
|
|
||||||
if (!editor.$mouseHandler.$clickSelection) {
|
|
||||||
if (!dragCursor) {
|
|
||||||
editor.moveCursorToPosition(pos);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dragCursor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (dragRange.contains(dragCursor.row, dragCursor.column)) {
|
|
||||||
dragCursor = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.clearSelection();
|
|
||||||
if (e && (e.ctrlKey || e.altKey)) {
|
|
||||||
var session = editor.session;
|
|
||||||
var newRange = session.insert(dragCursor, session.getTextRange(dragRange));
|
|
||||||
} else {
|
} else {
|
||||||
var newRange = editor.moveText(dragRange, dragCursor);
|
this.mousedownEvent.time = (new Date()).getTime();
|
||||||
|
this.setState("dragWait");
|
||||||
}
|
}
|
||||||
if (!newRange) {
|
|
||||||
dragCursor = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.selection.setSelectionRange(newRange);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onSelectionInterval = function() {
|
|
||||||
if (state == STATE_UNKNOWN) {
|
|
||||||
var distance = calcDistance(pageX, pageY, mousePageX, mousePageY);
|
|
||||||
var time = (new Date()).getTime();
|
|
||||||
|
|
||||||
if (distance > DRAG_OFFSET) {
|
|
||||||
state = STATE_SELECT;
|
|
||||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
|
||||||
onStartSelect(cursor);
|
|
||||||
}
|
|
||||||
else if ((time - mousedownTime) > editor.getDragDelay()) {
|
|
||||||
state = STATE_DRAG;
|
|
||||||
dragRange = editor.getSelectionRange();
|
|
||||||
var style = editor.getSelectionStyle();
|
|
||||||
dragSelectionMarker = editor.session.addMarker(dragRange, "ace_selection", style);
|
|
||||||
editor.clearSelection();
|
|
||||||
dom.addCssClass(editor.container, "ace_dragging");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == STATE_DRAG)
|
|
||||||
onDragSelectionInterval();
|
|
||||||
else if (state == STATE_SELECT)
|
|
||||||
onUpdateSelectionInterval();
|
|
||||||
};
|
|
||||||
|
|
||||||
function onStartSelect(pos) {
|
|
||||||
if (ev.getShiftKey()) {
|
|
||||||
editor.selection.selectToPosition(pos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!_self.$clickSelection) {
|
|
||||||
editor.moveCursorToPosition(pos);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state = STATE_SELECT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var onUpdateSelectionInterval = function() {
|
this.captureMouse(ev)
|
||||||
var anchor;
|
};
|
||||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
|
||||||
|
|
||||||
if (_self.$clickSelection) {
|
this.startSelect = function(pos) {
|
||||||
if (_self.$clickSelection.contains(cursor.row, cursor.column)) {
|
pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y);
|
||||||
editor.selection.setSelectionRange(_self.$clickSelection);
|
if (this.mousedownEvent.getShiftKey()) {
|
||||||
}
|
this.editor.selection.selectToPosition(pos);
|
||||||
else {
|
}
|
||||||
if (_self.$clickSelection.compare(cursor.row, cursor.column) == -1) {
|
else if (!this.$clickSelection) {
|
||||||
anchor = _self.$clickSelection.end;
|
this.editor.moveCursorToPosition(pos);
|
||||||
|
this.editor.selection.clearSelection();
|
||||||
|
}
|
||||||
|
this.setState("select");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.select = function() {
|
||||||
|
var anchor, editor = this.editor;
|
||||||
|
var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
|
||||||
|
|
||||||
|
if (this.$clickSelection) {
|
||||||
|
var cmp = this.$clickSelection.comparePoint(cursor);
|
||||||
|
|
||||||
|
if (cmp == -1) {
|
||||||
|
anchor = this.$clickSelection.end;
|
||||||
|
} else if (cmp == 1) {
|
||||||
|
anchor = this.$clickSelection.start;
|
||||||
|
} else {
|
||||||
|
cursor = this.$clickSelection.end;
|
||||||
|
anchor = this.$clickSelection.start;
|
||||||
|
}
|
||||||
|
editor.selection.setSelectionAnchor(anchor.row, anchor.column);
|
||||||
|
}
|
||||||
|
editor.selection.selectToPosition(cursor);
|
||||||
|
|
||||||
|
editor.renderer.scrollCursorIntoView();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.extendSelectionBy = function(unitName) {
|
||||||
|
var anchor, editor = this.editor;
|
||||||
|
var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
|
||||||
|
var range = editor.selection[unitName](cursor.row, cursor.column);
|
||||||
|
|
||||||
|
if (this.$clickSelection) {
|
||||||
|
var cmpStart = this.$clickSelection.comparePoint(range.start);
|
||||||
|
var cmpEnd = this.$clickSelection.comparePoint(range.end);
|
||||||
|
|
||||||
|
if (cmpStart == -1 && cmpEnd <= 0) {
|
||||||
|
anchor = this.$clickSelection.end;
|
||||||
|
cursor = range.start;
|
||||||
|
} else if (cmpEnd == 1 && cmpStart >= 0) {
|
||||||
|
anchor = this.$clickSelection.start;
|
||||||
|
cursor = range.end;
|
||||||
|
} else if (cmpStart == -1 && cmpEnd == 1) {
|
||||||
|
cursor = range.end;
|
||||||
|
anchor = range.start;
|
||||||
|
} else {
|
||||||
|
cursor = this.$clickSelection.end;
|
||||||
|
anchor = this.$clickSelection.start;
|
||||||
|
}
|
||||||
|
editor.selection.setSelectionAnchor(anchor.row, anchor.column);
|
||||||
|
}
|
||||||
|
editor.selection.selectToPosition(cursor);
|
||||||
|
|
||||||
|
editor.renderer.scrollCursorIntoView();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.startDrag = function() {
|
||||||
|
var editor = this.editor;
|
||||||
|
this.setState("drag");
|
||||||
|
this.dragRange = editor.getSelectionRange();
|
||||||
|
var style = editor.getSelectionStyle();
|
||||||
|
this.dragSelectionMarker = editor.session.addMarker(this.dragRange, "ace_selection", style);
|
||||||
|
editor.clearSelection();
|
||||||
|
dom.addCssClass(editor.container, "ace_dragging");
|
||||||
|
if (!this.$dragKeybinding) {
|
||||||
|
this.$dragKeybinding = {
|
||||||
|
handleKeyboard: function(data, hashId, keyString, keyCode) {
|
||||||
|
if (keyString == "esc")
|
||||||
|
return {command: this.command};
|
||||||
|
},
|
||||||
|
command: {
|
||||||
|
exec: function(editor) {
|
||||||
|
var self = editor.$mouseHandler;
|
||||||
|
self.dragCursor = null
|
||||||
|
self.dragEnd();
|
||||||
|
self.startSelect();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
anchor = _self.$clickSelection.start;
|
|
||||||
}
|
|
||||||
editor.selection.setSelectionAnchor(anchor.row, anchor.column);
|
|
||||||
editor.selection.selectToPosition(cursor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
editor.selection.selectToPosition(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.renderer.scrollCursorIntoView();
|
editor.keyBinding.addKeyboardHandler(this.$dragKeybinding);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onDragSelectionInterval = function() {
|
this.dragWait = function() {
|
||||||
dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
|
||||||
editor.moveCursorToPosition(dragCursor);
|
var time = (new Date()).getTime();
|
||||||
};
|
var editor = this.editor;
|
||||||
|
|
||||||
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
|
if (distance > DRAG_OFFSET) {
|
||||||
var timerId = setInterval(onSelectionInterval, 20);
|
this.startSelect();
|
||||||
|
} else if ((time - this.mousedownEvent.time) > editor.getDragDelay()) {
|
||||||
|
this.startDrag()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return ev.preventDefault();
|
this.dragWaitEnd = function(e) {
|
||||||
|
this.mousedownEvent.domEvent = e;
|
||||||
|
this.startSelect();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.drag = function() {
|
||||||
|
var editor = this.editor;
|
||||||
|
this.dragCursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
|
||||||
|
editor.moveCursorToPosition(this.dragCursor);
|
||||||
|
editor.renderer.scrollCursorIntoView();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.dragEnd = function(e) {
|
||||||
|
var editor = this.editor;
|
||||||
|
var dragCursor = this.dragCursor;
|
||||||
|
var dragRange = this.dragRange;
|
||||||
|
dom.removeCssClass(editor.container, "ace_dragging");
|
||||||
|
editor.session.removeMarker(this.dragSelectionMarker);
|
||||||
|
editor.keyBinding.removeKeyboardHandler(this.$dragKeybinding);
|
||||||
|
|
||||||
|
if (!dragCursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
editor.clearSelection();
|
||||||
|
if (e && (e.ctrlKey || e.altKey)) {
|
||||||
|
var session = editor.session;
|
||||||
|
var newRange = dragRange;
|
||||||
|
newRange.end = session.insert(dragCursor, session.getTextRange(dragRange));
|
||||||
|
newRange.start = dragCursor;
|
||||||
|
} else if (dragRange.contains(dragCursor.row, dragCursor.column)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
var newRange = editor.moveText(dragRange, dragCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newRange)
|
||||||
|
return;
|
||||||
|
|
||||||
|
editor.selection.setSelectionRange(newRange);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onDoubleClick = function(ev) {
|
this.onDoubleClick = function(ev) {
|
||||||
var pos = ev.getDocumentPosition();
|
var pos = ev.getDocumentPosition();
|
||||||
var editor = this.editor;
|
var editor = this.editor;
|
||||||
|
|
||||||
|
this.setState("selectByWords");
|
||||||
|
|
||||||
editor.moveCursorToPosition(pos);
|
editor.moveCursorToPosition(pos);
|
||||||
editor.selection.selectWord();
|
editor.selection.selectWord();
|
||||||
this.$clickSelection = editor.getSelectionRange();
|
this.$clickSelection = editor.getSelectionRange();
|
||||||
|
|
@ -252,6 +285,8 @@ function DefaultHandlers(editor) {
|
||||||
var pos = ev.getDocumentPosition();
|
var pos = ev.getDocumentPosition();
|
||||||
var editor = this.editor;
|
var editor = this.editor;
|
||||||
|
|
||||||
|
this.setState("selectByLines");
|
||||||
|
|
||||||
editor.moveCursorToPosition(pos);
|
editor.moveCursorToPosition(pos);
|
||||||
editor.selection.selectLine();
|
editor.selection.selectLine();
|
||||||
this.$clickSelection = editor.getSelectionRange();
|
this.$clickSelection = editor.getSelectionRange();
|
||||||
|
|
@ -262,14 +297,29 @@ function DefaultHandlers(editor) {
|
||||||
|
|
||||||
editor.selectAll();
|
editor.selectAll();
|
||||||
this.$clickSelection = editor.getSelectionRange();
|
this.$clickSelection = editor.getSelectionRange();
|
||||||
|
this.setState("select");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onScroll = function(ev) {
|
this.onScroll = function(ev) {
|
||||||
var editor = this.editor;
|
var editor = this.editor;
|
||||||
|
var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
|
||||||
|
if (isScrolable) {
|
||||||
|
this.$passScrollEvent = false;
|
||||||
|
} else {
|
||||||
|
if (this.$passScrollEvent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!this.$scrollStopTimeout) {
|
||||||
|
var self = this;
|
||||||
|
this.$scrollStopTimeout = setTimeout(function() {
|
||||||
|
self.$passScrollEvent = true;
|
||||||
|
self.$scrollStopTimeout = null;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
|
editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
|
||||||
if (editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed))
|
return ev.preventDefault();
|
||||||
return ev.preventDefault();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(DefaultHandlers.prototype);
|
}).call(DefaultHandlers.prototype);
|
||||||
|
|
|
||||||
|
|
@ -48,11 +48,8 @@ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
|
||||||
this.domEvent = domEvent;
|
this.domEvent = domEvent;
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
|
|
||||||
this.pageX = event.getDocumentX(domEvent);
|
this.x = this.clientX = domEvent.clientX;
|
||||||
this.pageY = event.getDocumentY(domEvent);
|
this.y = this.clientY = domEvent.clientY;
|
||||||
|
|
||||||
this.clientX = domEvent.clientX;
|
|
||||||
this.clientY = domEvent.clientY;
|
|
||||||
|
|
||||||
this.$pos = null;
|
this.$pos = null;
|
||||||
this.$inSelection = null;
|
this.$inSelection = null;
|
||||||
|
|
@ -87,9 +84,7 @@ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
|
||||||
if (this.$pos)
|
if (this.$pos)
|
||||||
return this.$pos;
|
return this.$pos;
|
||||||
|
|
||||||
var pageX = event.getDocumentX(this.domEvent);
|
this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY);
|
||||||
var pageY = event.getDocumentY(this.domEvent);
|
|
||||||
this.$pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);
|
|
||||||
return this.$pos;
|
return this.$pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ var MouseEvent = require("./mouse_event").MouseEvent;
|
||||||
var MouseHandler = function(editor) {
|
var MouseHandler = function(editor) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
|
|
||||||
new DefaultHandlers(editor);
|
new DefaultHandlers(this);
|
||||||
new DefaultGutterHandler(editor);
|
new DefaultGutterHandler(this);
|
||||||
|
|
||||||
event.addListener(editor.container, "mousedown", function(e) {
|
event.addListener(editor.container, "mousedown", function(e) {
|
||||||
editor.focus();
|
editor.focus();
|
||||||
|
|
@ -117,6 +117,44 @@ var MouseHandler = function(editor) {
|
||||||
this.editor._emit(name, mouseEvent);
|
this.editor._emit(name, mouseEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.setState = function(state) {
|
||||||
|
this.state = state;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.captureMouse = function(ev, state) {
|
||||||
|
if (state)
|
||||||
|
this.setState(state);
|
||||||
|
|
||||||
|
this.x = ev.x;
|
||||||
|
this.y = ev.y;
|
||||||
|
|
||||||
|
// do not move textarea during selection
|
||||||
|
var kt = this.editor.renderer.$keepTextAreaAtCursor;
|
||||||
|
this.editor.renderer.$keepTextAreaAtCursor = false;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var onMouseSelection = function(e) {
|
||||||
|
self.x = e.clientX;
|
||||||
|
self.y = e.clientY;
|
||||||
|
};
|
||||||
|
|
||||||
|
var onMouseSelectionEnd = function(e) {
|
||||||
|
clearInterval(timerId);
|
||||||
|
self[self.state + "End"] && self[self.state + "End"](e);
|
||||||
|
self.$clickSelection = null;
|
||||||
|
self.editor.renderer.$keepTextAreaAtCursor = kt;
|
||||||
|
self.editor.renderer.$moveTextAreaToCursor();
|
||||||
|
};
|
||||||
|
|
||||||
|
var onSelectionInterval = function() {
|
||||||
|
self[self.state] && self[self.state]();
|
||||||
|
}
|
||||||
|
|
||||||
|
event.capture(this.editor.container, onMouseSelection, onMouseSelectionEnd);
|
||||||
|
var timerId = setInterval(onSelectionInterval, 20);
|
||||||
|
|
||||||
|
ev.preventDefault();
|
||||||
|
};
|
||||||
}).call(MouseHandler.prototype);
|
}).call(MouseHandler.prototype);
|
||||||
|
|
||||||
exports.MouseHandler = MouseHandler;
|
exports.MouseHandler = MouseHandler;
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,10 @@ function onMouseDown(e) {
|
||||||
var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
|
var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
|
||||||
|
|
||||||
|
|
||||||
var mouseX = e.pageX, mouseY = e.pageY;
|
var mouseX = e.x, mouseY = e.y;
|
||||||
var onMouseSelection = function(e) {
|
var onMouseSelection = function(e) {
|
||||||
mouseX = event.getDocumentX(e);
|
mouseX = e.clientX;
|
||||||
mouseY = event.getDocumentY(e);
|
mouseY = e.clientY;
|
||||||
};
|
};
|
||||||
|
|
||||||
var blockSelect = function() {
|
var blockSelect = function() {
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,11 @@ var Selection = function(session) {
|
||||||
this.doc = session.getDocument();
|
this.doc = session.getDocument();
|
||||||
|
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.selectionLead = this.doc.createAnchor(0, 0);
|
this.lead = this.selectionLead = this.doc.createAnchor(0, 0);
|
||||||
this.selectionAnchor = this.doc.createAnchor(0, 0);
|
this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.selectionLead.on("change", function(e) {
|
this.lead.on("change", function(e) {
|
||||||
self._emit("changeCursor");
|
self._emit("changeCursor");
|
||||||
if (!self.$isEmpty)
|
if (!self.$isEmpty)
|
||||||
self._emit("changeSelection");
|
self._emit("changeSelection");
|
||||||
|
|
@ -93,8 +93,8 @@ var Selection = function(session) {
|
||||||
**/
|
**/
|
||||||
this.isEmpty = function() {
|
this.isEmpty = function() {
|
||||||
return (this.$isEmpty || (
|
return (this.$isEmpty || (
|
||||||
this.selectionAnchor.row == this.selectionLead.row &&
|
this.anchor.row == this.lead.row &&
|
||||||
this.selectionAnchor.column == this.selectionLead.column
|
this.anchor.column == this.lead.column
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ var Selection = function(session) {
|
||||||
* Gets the current position of the cursor.
|
* Gets the current position of the cursor.
|
||||||
**/
|
**/
|
||||||
this.getCursor = function() {
|
this.getCursor = function() {
|
||||||
return this.selectionLead.getPosition();
|
return this.lead.getPosition();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -128,7 +128,7 @@ var Selection = function(session) {
|
||||||
* Sets the row and column position of the anchor. This function also emits the `'changeSelection'` event.
|
* Sets the row and column position of the anchor. This function also emits the `'changeSelection'` event.
|
||||||
**/
|
**/
|
||||||
this.setSelectionAnchor = function(row, column) {
|
this.setSelectionAnchor = function(row, column) {
|
||||||
this.selectionAnchor.setPosition(row, column);
|
this.anchor.setPosition(row, column);
|
||||||
|
|
||||||
if (this.$isEmpty) {
|
if (this.$isEmpty) {
|
||||||
this.$isEmpty = false;
|
this.$isEmpty = false;
|
||||||
|
|
@ -146,7 +146,7 @@ var Selection = function(session) {
|
||||||
if (this.$isEmpty)
|
if (this.$isEmpty)
|
||||||
return this.getSelectionLead()
|
return this.getSelectionLead()
|
||||||
else
|
else
|
||||||
return this.selectionAnchor.getPosition();
|
return this.anchor.getPosition();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -155,7 +155,7 @@ var Selection = function(session) {
|
||||||
* Returns an object containing the `row` and `column` of the calling selection lead.
|
* Returns an object containing the `row` and `column` of the calling selection lead.
|
||||||
**/
|
**/
|
||||||
this.getSelectionLead = function() {
|
this.getSelectionLead = function() {
|
||||||
return this.selectionLead.getPosition();
|
return this.lead.getPosition();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -167,7 +167,7 @@ var Selection = function(session) {
|
||||||
**/
|
**/
|
||||||
this.shiftSelection = function(columns) {
|
this.shiftSelection = function(columns) {
|
||||||
if (this.$isEmpty) {
|
if (this.$isEmpty) {
|
||||||
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
|
this.moveCursorTo(this.lead.row, this.lead.column + columns);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -192,8 +192,8 @@ var Selection = function(session) {
|
||||||
* Returns `true` if the selection is going backwards in the document.
|
* Returns `true` if the selection is going backwards in the document.
|
||||||
**/
|
**/
|
||||||
this.isBackwards = function() {
|
this.isBackwards = function() {
|
||||||
var anchor = this.selectionAnchor;
|
var anchor = this.anchor;
|
||||||
var lead = this.selectionLead;
|
var lead = this.lead;
|
||||||
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
|
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -203,8 +203,8 @@ var Selection = function(session) {
|
||||||
* [Returns the [[Range `Range`]] for the selected text.]{: #Selection.getRange}
|
* [Returns the [[Range `Range`]] for the selected text.]{: #Selection.getRange}
|
||||||
**/
|
**/
|
||||||
this.getRange = function() {
|
this.getRange = function() {
|
||||||
var anchor = this.selectionAnchor;
|
var anchor = this.anchor;
|
||||||
var lead = this.selectionLead;
|
var lead = this.lead;
|
||||||
|
|
||||||
if (this.isEmpty())
|
if (this.isEmpty())
|
||||||
return Range.fromPoints(lead, lead);
|
return Range.fromPoints(lead, lead);
|
||||||
|
|
@ -249,18 +249,23 @@ var Selection = function(session) {
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
this.setSelectionRange = function(range, reverse) {
|
this.setSelectionRange = function(range, reverse) {
|
||||||
if (reverse) {
|
if (range.isEmpty()) {
|
||||||
this.setSelectionAnchor(range.end.row, range.end.column);
|
this.lead.setPosition(range.start.row, range.start.column);
|
||||||
this.selectTo(range.start.row, range.start.column);
|
this.clearSelection();
|
||||||
|
} else if (reverse) {
|
||||||
|
this.$isEmpty = false;
|
||||||
|
this.anchor.setPosition(range.end.row, range.end.column);
|
||||||
|
this.lead.setPosition(range.start.row, range.start.column);
|
||||||
} else {
|
} else {
|
||||||
this.setSelectionAnchor(range.start.row, range.start.column);
|
this.$isEmpty = false;
|
||||||
this.selectTo(range.end.row, range.end.column);
|
this.anchor.setPosition(range.start.row, range.start.column);
|
||||||
|
this.lead.setPosition(range.end.row, range.end.column);
|
||||||
}
|
}
|
||||||
this.$desiredColumn = null;
|
this.$desiredColumn = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$moveSelection = function(mover) {
|
this.$moveSelection = function(mover) {
|
||||||
var lead = this.selectionLead;
|
var lead = this.lead;
|
||||||
if (this.$isEmpty)
|
if (this.$isEmpty)
|
||||||
this.setSelectionAnchor(lead.row, lead.column);
|
this.setSelectionAnchor(lead.row, lead.column);
|
||||||
|
|
||||||
|
|
@ -391,7 +396,7 @@ var Selection = function(session) {
|
||||||
**/
|
**/
|
||||||
this.getWordRange = function(row, column) {
|
this.getWordRange = function(row, column) {
|
||||||
if (typeof column == "undefined") {
|
if (typeof column == "undefined") {
|
||||||
var cursor = row || this.selectionLead;
|
var cursor = row || this.lead;
|
||||||
row = cursor.row;
|
row = cursor.row;
|
||||||
column = cursor.column;
|
column = cursor.column;
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +419,7 @@ var Selection = function(session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getLineRange = function(row, excludeLastChar) {
|
this.getLineRange = function(row, excludeLastChar) {
|
||||||
var rowStart = typeof row == "number" ? row : this.selectionLead.row;
|
var rowStart = typeof row == "number" ? row : this.lead.row;
|
||||||
var rowEnd;
|
var rowEnd;
|
||||||
|
|
||||||
var foldLine = this.session.getFoldLine(rowStart);
|
var foldLine = this.session.getFoldLine(rowStart);
|
||||||
|
|
@ -463,7 +468,7 @@ var Selection = function(session) {
|
||||||
* Moves the cursor left one column.
|
* Moves the cursor left one column.
|
||||||
**/
|
**/
|
||||||
this.moveCursorLeft = function() {
|
this.moveCursorLeft = function() {
|
||||||
var cursor = this.selectionLead.getPosition(),
|
var cursor = this.lead.getPosition(),
|
||||||
fold;
|
fold;
|
||||||
|
|
||||||
if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {
|
if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {
|
||||||
|
|
@ -489,19 +494,19 @@ var Selection = function(session) {
|
||||||
* Moves the cursor right one column.
|
* Moves the cursor right one column.
|
||||||
**/
|
**/
|
||||||
this.moveCursorRight = function() {
|
this.moveCursorRight = function() {
|
||||||
var cursor = this.selectionLead.getPosition(),
|
var cursor = this.lead.getPosition(),
|
||||||
fold;
|
fold;
|
||||||
if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
|
if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
|
||||||
this.moveCursorTo(fold.end.row, fold.end.column);
|
this.moveCursorTo(fold.end.row, fold.end.column);
|
||||||
}
|
}
|
||||||
else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
|
else if (this.lead.column == this.doc.getLine(this.lead.row).length) {
|
||||||
if (this.selectionLead.row < this.doc.getLength() - 1) {
|
if (this.lead.row < this.doc.getLength() - 1) {
|
||||||
this.moveCursorTo(this.selectionLead.row + 1, 0);
|
this.moveCursorTo(this.lead.row + 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var tabSize = this.session.getTabSize();
|
var tabSize = this.session.getTabSize();
|
||||||
var cursor = this.selectionLead;
|
var cursor = this.lead;
|
||||||
if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize)
|
if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize)
|
||||||
this.moveCursorBy(0, tabSize);
|
this.moveCursorBy(0, tabSize);
|
||||||
else
|
else
|
||||||
|
|
@ -515,8 +520,8 @@ var Selection = function(session) {
|
||||||
* Moves the cursor to the start of the line.
|
* Moves the cursor to the start of the line.
|
||||||
**/
|
**/
|
||||||
this.moveCursorLineStart = function() {
|
this.moveCursorLineStart = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.lead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.lead.column;
|
||||||
var screenRow = this.session.documentToScreenRow(row, column);
|
var screenRow = this.session.documentToScreenRow(row, column);
|
||||||
|
|
||||||
// Determ the doc-position of the first character at the screen line.
|
// Determ the doc-position of the first character at the screen line.
|
||||||
|
|
@ -548,7 +553,7 @@ var Selection = function(session) {
|
||||||
* Moves the cursor to the end of the line.
|
* Moves the cursor to the end of the line.
|
||||||
**/
|
**/
|
||||||
this.moveCursorLineEnd = function() {
|
this.moveCursorLineEnd = function() {
|
||||||
var lead = this.selectionLead;
|
var lead = this.lead;
|
||||||
var lastRowColumnPosition =
|
var lastRowColumnPosition =
|
||||||
this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
|
this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
|
||||||
this.moveCursorTo(
|
this.moveCursorTo(
|
||||||
|
|
@ -583,8 +588,8 @@ var Selection = function(session) {
|
||||||
* Moves the cursor to the word on the right.
|
* Moves the cursor to the word on the right.
|
||||||
**/
|
**/
|
||||||
this.moveCursorLongWordRight = function() {
|
this.moveCursorLongWordRight = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.lead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.lead.column;
|
||||||
var line = this.doc.getLine(row);
|
var line = this.doc.getLine(row);
|
||||||
var rightOfCursor = line.substring(column);
|
var rightOfCursor = line.substring(column);
|
||||||
|
|
||||||
|
|
@ -630,8 +635,8 @@ var Selection = function(session) {
|
||||||
* Moves the cursor to the word on the left.
|
* Moves the cursor to the word on the left.
|
||||||
**/
|
**/
|
||||||
this.moveCursorLongWordLeft = function() {
|
this.moveCursorLongWordLeft = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.lead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.lead.column;
|
||||||
|
|
||||||
// skip folds
|
// skip folds
|
||||||
var fold;
|
var fold;
|
||||||
|
|
@ -712,8 +717,8 @@ var Selection = function(session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorShortWordRight = function() {
|
this.moveCursorShortWordRight = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.lead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.lead.column;
|
||||||
var line = this.doc.getLine(row);
|
var line = this.doc.getLine(row);
|
||||||
var rightOfCursor = line.substring(column);
|
var rightOfCursor = line.substring(column);
|
||||||
|
|
||||||
|
|
@ -730,8 +735,8 @@ var Selection = function(session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorShortWordLeft = function() {
|
this.moveCursorShortWordLeft = function() {
|
||||||
var row = this.selectionLead.row;
|
var row = this.lead.row;
|
||||||
var column = this.selectionLead.column;
|
var column = this.lead.column;
|
||||||
|
|
||||||
var fold;
|
var fold;
|
||||||
if (fold = this.session.getFoldAt(row, column, -1))
|
if (fold = this.session.getFoldAt(row, column, -1))
|
||||||
|
|
@ -770,8 +775,8 @@ var Selection = function(session) {
|
||||||
**/
|
**/
|
||||||
this.moveCursorBy = function(rows, chars) {
|
this.moveCursorBy = function(rows, chars) {
|
||||||
var screenPos = this.session.documentToScreenPosition(
|
var screenPos = this.session.documentToScreenPosition(
|
||||||
this.selectionLead.row,
|
this.lead.row,
|
||||||
this.selectionLead.column
|
this.lead.column
|
||||||
);
|
);
|
||||||
|
|
||||||
if (chars === 0) {
|
if (chars === 0) {
|
||||||
|
|
@ -814,7 +819,7 @@ var Selection = function(session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$keepDesiredColumnOnChange = true;
|
this.$keepDesiredColumnOnChange = true;
|
||||||
this.selectionLead.setPosition(row, column);
|
this.lead.setPosition(row, column);
|
||||||
this.$keepDesiredColumnOnChange = false;
|
this.$keepDesiredColumnOnChange = false;
|
||||||
|
|
||||||
if (!keepDesiredColumn)
|
if (!keepDesiredColumn)
|
||||||
|
|
@ -836,8 +841,8 @@ var Selection = function(session) {
|
||||||
|
|
||||||
// remove listeners from document
|
// remove listeners from document
|
||||||
this.detach = function() {
|
this.detach = function() {
|
||||||
this.selectionLead.detach();
|
this.lead.detach();
|
||||||
this.selectionAnchor.detach();
|
this.anchor.detach();
|
||||||
this.session = this.doc = null;
|
this.session = this.doc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,9 @@ var VirtualRenderer = function(container, theme) {
|
||||||
// // Imports CSS once per DOM document ('ace_editor' serves as an identifier).
|
// // Imports CSS once per DOM document ('ace_editor' serves as an identifier).
|
||||||
// dom.importCssString(editorCss, "ace_editor", container.ownerDocument);
|
// dom.importCssString(editorCss, "ace_editor", container.ownerDocument);
|
||||||
|
|
||||||
|
// in IE <= 9 the native cursor always shines through
|
||||||
|
this.$keepTextAreaAtCursor = !useragent.isIE;
|
||||||
|
|
||||||
dom.addCssClass(container, "ace_editor");
|
dom.addCssClass(container, "ace_editor");
|
||||||
|
|
||||||
this.setTheme(theme);
|
this.setTheme(theme);
|
||||||
|
|
@ -99,6 +102,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.content.className = "ace_content";
|
this.content.className = "ace_content";
|
||||||
this.scroller.appendChild(this.content);
|
this.scroller.appendChild(this.content);
|
||||||
|
|
||||||
|
this.setHighlightGutterLine(true);
|
||||||
this.$gutterLayer = new GutterLayer(this.$gutter);
|
this.$gutterLayer = new GutterLayer(this.$gutter);
|
||||||
this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));
|
this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));
|
||||||
this.setFadeFoldWidgets(true);
|
this.setFadeFoldWidgets(true);
|
||||||
|
|
@ -449,6 +453,33 @@ var VirtualRenderer = function(container, theme) {
|
||||||
dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets");
|
dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$highlightGutterLine = false;
|
||||||
|
this.setHighlightGutterLine = function(shouldHighlight) {
|
||||||
|
if (this.$highlightGutterLine == shouldHighlight)
|
||||||
|
return;
|
||||||
|
this.$highlightGutterLine = shouldHighlight;
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.$gutterLineHighlight) {
|
||||||
|
this.$gutterLineHighlight = dom.createElement("div");
|
||||||
|
this.$gutterLineHighlight.className = "ace_gutter_active_line";
|
||||||
|
this.$gutter.appendChild(this.$gutterLineHighlight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none";
|
||||||
|
this.$updateGutterLineHighlight();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getHighlightGutterLine = function() {
|
||||||
|
return this.$highlightGutterLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$updateGutterLineHighlight = function() {
|
||||||
|
this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top + "px";
|
||||||
|
this.$gutterLineHighlight.style.height = this.layerConfig.lineHeight + "px";
|
||||||
|
};
|
||||||
|
|
||||||
this.$updatePrintMargin = function() {
|
this.$updatePrintMargin = function() {
|
||||||
var containerEl;
|
var containerEl;
|
||||||
|
|
||||||
|
|
@ -496,30 +527,23 @@ var VirtualRenderer = function(container, theme) {
|
||||||
return this.container;
|
return this.container;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// move text input over the cursor
|
||||||
* VirtualRenderer.moveTextAreaToCursor(textarea) -> Void
|
// this is required for iOS and IME
|
||||||
* - textarea (DOMElement): A text area to work with
|
this.$moveTextAreaToCursor = function() {
|
||||||
*
|
if (!this.$keepTextAreaAtCursor)
|
||||||
* Changes the position of `textarea` to where the cursor is pointing.
|
|
||||||
**/
|
|
||||||
this.moveTextAreaToCursor = function(textarea) {
|
|
||||||
// in IE the native cursor always shines through
|
|
||||||
// this persists in IE9
|
|
||||||
if (useragent.isIE)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.layerConfig.lastRow === 0)
|
var posTop = this.$cursorLayer.$pixelPos.top;
|
||||||
|
var posLeft = this.$cursorLayer.$pixelPos.left;
|
||||||
|
posTop -= this.layerConfig.offset;
|
||||||
|
|
||||||
|
if (posTop < 0 || posTop > this.layerConfig.height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var pos = this.$cursorLayer.getPixelPosition();
|
posLeft += (this.showGutter ? this.$gutterLayer.gutterWidth : 0) - this.scrollLeft;
|
||||||
if (!pos)
|
var bounds = this.container.getBoundingClientRect();
|
||||||
return;
|
this.textarea.style.left = (bounds.left + posLeft) + "px";
|
||||||
|
this.textarea.style.top = (bounds.top + posTop) + "px";
|
||||||
var bounds = this.content.getBoundingClientRect();
|
|
||||||
var offset = this.layerConfig.offset;
|
|
||||||
|
|
||||||
textarea.style.left = (bounds.left + pos.left) + "px";
|
|
||||||
textarea.style.top = (bounds.top + pos.top - this.scrollTop + offset) + "px";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -640,6 +664,8 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.$markerBack.update(this.layerConfig);
|
this.$markerBack.update(this.layerConfig);
|
||||||
this.$markerFront.update(this.layerConfig);
|
this.$markerFront.update(this.layerConfig);
|
||||||
this.$cursorLayer.update(this.layerConfig);
|
this.$cursorLayer.update(this.layerConfig);
|
||||||
|
this.$moveTextAreaToCursor();
|
||||||
|
this.$highlightGutterLine && this.$updateGutterLineHighlight();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,6 +682,8 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.$markerBack.update(this.layerConfig);
|
this.$markerBack.update(this.layerConfig);
|
||||||
this.$markerFront.update(this.layerConfig);
|
this.$markerFront.update(this.layerConfig);
|
||||||
this.$cursorLayer.update(this.layerConfig);
|
this.$cursorLayer.update(this.layerConfig);
|
||||||
|
this.$moveTextAreaToCursor();
|
||||||
|
this.$highlightGutterLine && this.$updateGutterLineHighlight();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -675,8 +703,11 @@ var VirtualRenderer = function(container, theme) {
|
||||||
this.$gutterLayer.update(this.layerConfig);
|
this.$gutterLayer.update(this.layerConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes & this.CHANGE_CURSOR)
|
if (changes & this.CHANGE_CURSOR) {
|
||||||
this.$cursorLayer.update(this.layerConfig);
|
this.$cursorLayer.update(this.layerConfig);
|
||||||
|
this.$moveTextAreaToCursor();
|
||||||
|
this.$highlightGutterLine && this.$updateGutterLineHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
|
if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
|
||||||
this.$markerFront.update(this.layerConfig);
|
this.$markerFront.update(this.layerConfig);
|
||||||
|
|
@ -753,7 +784,7 @@ var VirtualRenderer = function(container, theme) {
|
||||||
// For debugging.
|
// For debugging.
|
||||||
// console.log(JSON.stringify(this.layerConfig));
|
// console.log(JSON.stringify(this.layerConfig));
|
||||||
|
|
||||||
this.$gutterLayer.element.style.marginTop = (-offset) + "px";
|
this.$gutter.style.marginTop = (-offset) + "px";
|
||||||
this.content.style.marginTop = (-offset) + "px";
|
this.content.style.marginTop = (-offset) + "px";
|
||||||
this.content.style.width = longestLine + 2 * this.$padding + "px";
|
this.content.style.width = longestLine + 2 * this.$padding + "px";
|
||||||
this.content.style.height = minHeight + "px";
|
this.content.style.height = minHeight + "px";
|
||||||
|
|
@ -1103,14 +1134,24 @@ var VirtualRenderer = function(container, theme) {
|
||||||
// todo: handle horizontal scrolling
|
// todo: handle horizontal scrolling
|
||||||
};
|
};
|
||||||
|
|
||||||
this.screenToTextCoordinates = function(pageX, pageY) {
|
this.pixelToScreenCoordinates = function(x, y) {
|
||||||
|
var canvasPos = this.scroller.getBoundingClientRect();
|
||||||
|
|
||||||
|
var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth;
|
||||||
|
var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight);
|
||||||
|
var col = Math.round(offset);
|
||||||
|
|
||||||
|
return {row: row, column: col, side: offset - col > 0 ? 1 : -1};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.screenToTextCoordinates = function(x, y) {
|
||||||
var canvasPos = this.scroller.getBoundingClientRect();
|
var canvasPos = this.scroller.getBoundingClientRect();
|
||||||
|
|
||||||
var col = Math.round(
|
var col = Math.round(
|
||||||
(pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth
|
(x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth
|
||||||
);
|
);
|
||||||
var row = Math.floor(
|
var row = Math.floor(
|
||||||
(pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight
|
(y + this.scrollTop - canvasPos.top) / this.lineHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.session.screenToDocumentPosition(row, Math.max(col, 0));
|
return this.session.screenToDocumentPosition(row, Math.max(col, 0));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue