diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index a2fea74f..adf9bd73 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -306,13 +306,7 @@ var Autocomplete = function() { }; this.cancelContextMenu = function() { - var stop = function(e) { - this.editor.off("nativecontextmenu", stop); - if (e && e.domEvent) - event.stopEvent(e.domEvent); - }.bind(this); - setTimeout(stop, 10); - this.editor.on("nativecontextmenu", stop); + this.editor.$mouseHandler.cancelContextMenu(); }; }).call(Autocomplete.prototype); diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js index 39d115b4..612b6a34 100644 --- a/lib/ace/lib/event.js +++ b/lib/ace/lib/event.js @@ -85,7 +85,7 @@ exports.preventDefault = function(e) { exports.getButton = function(e) { if (e.type == "dblclick") return 0; - if (e.type == "contextmenu" || (e.ctrlKey && useragent.isMac)) + if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) return 2; // DOM Event @@ -183,7 +183,7 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac if (!timer || isNewClick) clicks = 1; if (timer) - clearTimeout(timer) + clearTimeout(timer); timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); if (clicks == 1) { diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index c7573e94..a991a849 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -157,6 +157,17 @@ var MouseHandler = function(editor) { var timerId = setInterval(onCaptureInterval, 20); }; this.releaseMouse = null; + this.cancelContextMenu = function() { + var stop = function(e) { + if (e && e.domEvent && e.domEvent.type != "contextmenu") + return; + this.editor.off("nativecontextmenu", stop); + if (e && e.domEvent) + event.stopEvent(e.domEvent); + }.bind(this); + setTimeout(stop, 10); + this.editor.on("nativecontextmenu", stop); + }; }).call(MouseHandler.prototype); config.defineOptions(MouseHandler.prototype, "mouseHandler", { diff --git a/lib/ace/mouse/multi_select_handler.js b/lib/ace/mouse/multi_select_handler.js index 88dc6668..0620f8f5 100644 --- a/lib/ace/mouse/multi_select_handler.js +++ b/lib/ace/mouse/multi_select_handler.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { var event = require("../lib/event"); +var useragent = require("../lib/useragent"); // mouse function isSamePoint(p1, p2) { @@ -41,8 +42,12 @@ function onMouseDown(e) { var ev = e.domEvent; var alt = ev.altKey; var shift = ev.shiftKey; - var ctrl = e.getAccelKey(); + var ctrl = ev.ctrlKey; + var accel = e.getAccelKey(); var button = e.getButton(); + + if (ctrl && useragent.isMac) + button = ev.button; if (e.editor.inMultiSelectMode && button == 2) { e.editor.textInput.onContextMenu(e.domEvent); @@ -54,6 +59,9 @@ function onMouseDown(e) { e.editor.exitMultiSelectMode(); return; } + + if (button !== 0) + return; var editor = e.editor; var selection = editor.selection; @@ -90,10 +98,28 @@ function onMouseDown(e) { var session = editor.session; var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); var screenCursor = screenAnchor; - + var selectionMode; + if (editor.$mouseHandler.$enableJumpToDef) { + if (ctrl && alt || accel && alt) + selectionMode = "add"; + else if (alt) + selectionMode = "block"; + } else { + if (accel && !alt) { + selectionMode = "add"; + if (!isMultiSelect && shift) + return; + } else if (alt) { + selectionMode = "block"; + } + } + + if (selectionMode && useragent.isMac && ev.ctrlKey) { + editor.$mouseHandler.cancelContextMenu(); + } - if (ctrl && !alt && !shift && button === 0) { + if (selectionMode == "add") { if (!isMultiSelect && inSelection) return; // dragging @@ -104,23 +130,34 @@ function onMouseDown(e) { var oldRange = selection.rangeList.rangeAtPoint(pos); + editor.$blockScrolling++; + editor.inVirtualSelectionMode = true; + + if (shift) { + oldRange = null; + range = selection.ranges[0]; + editor.removeSelectionMarker(range); + } editor.once("mouseup", function() { var tmpSel = selection.toOrientedRange(); if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) selection.substractPoint(tmpSel.cursor); else { - if (range) { + if (shift) { + selection.substractPoint(range.cursor); + } else if (range) { editor.removeSelectionMarker(range); selection.addRange(range); } selection.addRange(tmpSel); } editor.$blockScrolling--; + editor.inVirtualSelectionMode = false; }); - } else if (alt && button === 0) { + } else if (selectionMode == "block") { e.stop(); if (isMultiSelect && !ctrl) diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index b079e387..ef0f7a2e 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -76,7 +76,7 @@ var EditSession = require("./edit_session").EditSession; if (!range) return; - if (!this.inMultiSelectMode && this.rangeCount == 0) { + if (!this.inMultiSelectMode && this.rangeCount === 0) { var oldRange = this.toOrientedRange(); this.rangeList.add(oldRange); this.rangeList.add(range); @@ -168,7 +168,7 @@ var EditSession = require("./edit_session").EditSession; this._signal("removeRange", {ranges: removed}); - if (this.rangeCount == 0 && this.inMultiSelectMode) { + if (this.rangeCount === 0 && this.inMultiSelectMode) { this.inMultiSelectMode = false; this._signal("singleSelect"); this.session.$undoSelect = true; @@ -543,6 +543,19 @@ var Editor = require("./editor").Editor; } return text; }; + + this.$checkMultiselectChange = function(e, anchor) { + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var range = this.multiSelect.ranges[0]; + if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor) + return; + var pos = anchor == this.multiSelect.anchor + ? range.cursor == range.start ? range.end : range.start + : range.cursor; + if (!isSamePoint(pos, anchor)) + this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); + } + }; // todo this should change when paste becomes a command this.onPaste = function(text) { @@ -742,8 +755,15 @@ var Editor = require("./editor").Editor; var session = this.session; var sel = session.multiSelect; var ranges = sel.ranges; - - if (!ranges.length) { + // filter out ranges on same row + var row = -1; + var sameRowRanges = ranges.filter(function(r) { + if (r.cursor.row == row) + return true; + row = r.cursor.row; + }); + + if (!ranges.length || sameRowRanges.length == ranges.length - 1) { var range = this.selection.getRange(); var fr = range.start.row, lr = range.end.row; var guessRange = fr == lr; @@ -769,14 +789,9 @@ var Editor = require("./editor").Editor; } this.selection.setRange(range); } else { - // filter out ranges on same row - var row = -1; - var sameRowRanges = ranges.filter(function(r) { - if (r.cursor.row == row) - return true; - row = r.cursor.row; + sameRowRanges.forEach(function(r) { + sel.substractPoint(r.cursor); }); - sel.$onRemoveRange(sameRowRanges); var maxCol = 0; var minSpace = Infinity; @@ -851,19 +866,19 @@ var Editor = require("./editor").Editor; function alignLeft(m) { return !m[2] ? m[0] : spaces(startW) + m[2] + spaces(textW - m[2].length + endW) - + m[4].replace(/^([=:])\s+/, "$1 ") + + m[4].replace(/^([=:])\s+/, "$1 "); } function alignRight(m) { return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2] + spaces(endW, " ") - + m[4].replace(/^([=:])\s+/, "$1 ") + + m[4].replace(/^([=:])\s+/, "$1 "); } function unAlign(m) { return !m[2] ? m[0] : spaces(startW) + m[2] + spaces(endW) - + m[4].replace(/^([=:])\s+/, "$1 ") + + m[4].replace(/^([=:])\s+/, "$1 "); } - } + }; }).call(Editor.prototype); @@ -884,17 +899,21 @@ exports.onSessionChange = function(e) { var oldSession = e.oldSession; if (oldSession) { - oldSession.multiSelect.removeEventListener("addRange", this.$onAddRange); - oldSession.multiSelect.removeEventListener("removeRange", this.$onRemoveRange); - oldSession.multiSelect.removeEventListener("multiSelect", this.$onMultiSelect); - oldSession.multiSelect.removeEventListener("singleSelect", this.$onSingleSelect); + oldSession.multiSelect.off("addRange", this.$onAddRange); + oldSession.multiSelect.off("removeRange", this.$onRemoveRange); + oldSession.multiSelect.off("multiSelect", this.$onMultiSelect); + oldSession.multiSelect.off("singleSelect", this.$onSingleSelect); + oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange); + oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange); } session.multiSelect.on("addRange", this.$onAddRange); session.multiSelect.on("removeRange", this.$onRemoveRange); session.multiSelect.on("multiSelect", this.$onMultiSelect); session.multiSelect.on("singleSelect", this.$onSingleSelect); - + session.multiSelect.lead.on("change", this.$checkMultiselectChange); + session.multiSelect.anchor.on("change", this.$checkMultiselectChange); + // this.$onSelectionChange = this.onSelectionChange.bind(this); if (this.inMultiSelectMode != session.selection.inMultiSelectMode) { @@ -916,6 +935,7 @@ function MultiSelect(editor) { editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor); + editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor); editor.$multiselectOnSessionChange(editor); editor.on("changeSession", editor.$multiselectOnSessionChange); @@ -969,7 +989,7 @@ require("./config").defineOptions(Editor.prototype, "editor", { }, value: true } -}) +}); diff --git a/lib/ace/selection.js b/lib/ace/selection.js index e113d8ad..63bc9668 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -37,7 +37,6 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; /** - * * Contains the cursor position and the text selection of an edit session. * * The row/columns used in the selection are in document coordinates representing ths coordinates as thez appear in the document before applying soft wrap and folding. @@ -49,22 +48,16 @@ var Range = require("./range").Range; * Emitted when the cursor position changes. * @event changeCursor * - * - * **/ /** * Emitted when the cursor selection changes. + * * @event changeSelection - * - * - * **/ /** * Creates a new `Selection` object. * @param {EditSession} session The session to use - * - * - * + * * @constructor **/ var Selection = function(session) {