From 6f7a33e39b0974ef55bf64e32f856438c6cd11ce Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 25 Feb 2013 12:30:58 +0400 Subject: [PATCH] allow multiple selections with shared edges --- lib/ace/mouse/default_handlers.js | 4 ++-- lib/ace/multi_select.js | 8 ++++++-- lib/ace/range_list.js | 31 ++++++++++++++++++------------- lib/ace/range_list_test.js | 21 ++++++++++++++++++++- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index 3a7e97af..af741ce6 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -84,14 +84,14 @@ function DefaultHandlers(mouseHandler) { // selection if (inSelection && !editor.isFocused()) { editor.focus(); - if (this.$focusTimout && !this.$clickSelection) { + if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) { this.setState("focusWait"); this.captureMouse(ev); return ev.preventDefault(); } } - if (!inSelection || this.$clickSelection || ev.getShiftKey()) { + if (!inSelection || this.$clickSelection || ev.getShiftKey() || editor.inMultiSelectMode) { // Directly pick STATE_SELECT, since the user is not clicking inside // a selection. this.startSelect(pos); diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 9ae3b847..3c2a526f 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -78,9 +78,13 @@ var EditSession = require("./edit_session").EditSession; if (!this.inMultiSelectMode && this.rangeCount == 0) { var oldRange = this.toOrientedRange(); - if (range.intersects(oldRange)) + this.rangeList.add(oldRange); + this.rangeList.add(range); + if (this.rangeList.ranges.length != 2) { + this.rangeList.removeAll(); return $blockChangeEvents || this.fromOrientedRange(range); - + } + this.rangeList.removeAll(); this.rangeList.add(oldRange); this.$onAddRange(oldRange); } diff --git a/lib/ace/range_list.js b/lib/ace/range_list.js index 2e1900d3..ed0a5d2d 100644 --- a/lib/ace/range_list.js +++ b/lib/ace/range_list.js @@ -40,19 +40,18 @@ var RangeList = function() { (function() { this.comparePoints = comparePoints; - this.pointIndex = function(pos, startIndex) { + this.pointIndex = function(pos, excludeEdges, startIndex) { var list = this.ranges; for (var i = startIndex || 0; i < list.length; i++) { var range = list[i]; - var cmp = comparePoints(pos, range.end); - - if (cmp > 0) + var cmpEnd = comparePoints(pos, range.end); + if (cmpEnd > 0) continue; - if (cmp == 0) - return i; - cmp = comparePoints(pos, range.start); - if (cmp >= 0) + var cmpStart = comparePoints(pos, range.start); + if (cmpEnd === 0) + return excludeEdges && cmpStart !== 0 ? -i-2 : i; + if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) return i; return -i-1; @@ -61,17 +60,17 @@ var RangeList = function() { }; this.add = function(range) { - var startIndex = this.pointIndex(range.start); + var excludeEdges = !range.isEmpty(); + var startIndex = this.pointIndex(range.start, excludeEdges); if (startIndex < 0) startIndex = -startIndex - 1; - var endIndex = this.pointIndex(range.end, startIndex); + var endIndex = this.pointIndex(range.end, excludeEdges, startIndex); if (endIndex < 0) endIndex = -endIndex - 1; else endIndex++; - return this.ranges.splice(startIndex, endIndex - startIndex, range); }; @@ -102,7 +101,7 @@ var RangeList = function() { if (cmp < 0) continue; - if (cmp == 0 && !(range.isEmpty() || next.isEmpty())) + if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) continue; if (comparePoints(range.end, next.end) < 0) { @@ -198,10 +197,16 @@ var RangeList = function() { break; if (r.start.row == startRow && r.start.column >= start.column ) { + r.start.column += colDiff; r.start.row += lineDif; } - if (r.end.row == startRow && r.end.column >= start.column) { + if (r.end.row == startRow && r.end.column >= start.column) { + // special handling for the case when two ranges share an edge + if (r.end.column == start.column && colDiff > 0 && i < n - 1) { + if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) + r.end.column -= colDiff; + } r.end.column += colDiff; r.end.row += lineDif; } diff --git a/lib/ace/range_list_test.js b/lib/ace/range_list_test.js index 8623a945..82e7da67 100644 --- a/lib/ace/range_list_test.js +++ b/lib/ace/range_list_test.js @@ -72,6 +72,26 @@ module.exports = { assert.equal(rangeList.pointIndex({row: 8, column: 9}), 2); assert.equal(rangeList.pointIndex({row: 18, column: 9}), -4); }, + + "test: rangeList pointIndex excludeEdges": function() { + var rangeList = new RangeList(); + rangeList.ranges = [ + new Range(1,2,3,4), + new Range(4,2,5,4), + new Range(8,8,9,9), + new Range(10,10,10,10) + ]; + + assert.equal(rangeList.pointIndex({row: 0, column: 1}, true), -1); + assert.equal(rangeList.pointIndex({row: 1, column: 2}, true), -1); + assert.equal(rangeList.pointIndex({row: 1, column: 3}, true), 0); + assert.equal(rangeList.pointIndex({row: 3, column: 4}, true), -2); + assert.equal(rangeList.pointIndex({row: 4, column: 1}, true), -2); + assert.equal(rangeList.pointIndex({row: 5, column: 1}, true), 1); + assert.equal(rangeList.pointIndex({row: 8, column: 9}, true), 2); + assert.equal(rangeList.pointIndex({row: 10, column: 10}, true), 3); + assert.equal(rangeList.pointIndex({row: 18, column: 9}, true), -5); + }, "test: rangeList add": function() { var rangeList = new RangeList(); @@ -153,7 +173,6 @@ module.exports = { rangeList.substractPoint({row: 6, column: 7}); assert.equal(rangeList.ranges.length, 2); } - }; });