overuse of events is bad:(

This commit is contained in:
nightwing 2012-04-03 00:06:07 +04:00
commit 346ae096b3
5 changed files with 581 additions and 503 deletions

View file

@ -70,6 +70,16 @@ exports.defaultCommands = [{
exec: function(editor) { editor.selectMoreLines(1); }, exec: function(editor) { editor.selectMoreLines(1); },
bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
readonly: true readonly: true
}, {
name: "addCursorAboveSkipCurrent",
exec: function(editor) { editor.selectMoreLines(-1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
readonly: true
}, {
name: "addCursorBelowSkipCurrent",
exec: function(editor) { editor.selectMoreLines(1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
readonly: true
}, { }, {
name: "selectMoreBefore", name: "selectMoreBefore",
exec: function(editor) { editor.selectMore(-1); }, exec: function(editor) { editor.selectMore(-1); },

View file

@ -50,11 +50,11 @@ function onMouseDown(e) {
var ev = e.domEvent; var ev = e.domEvent;
var alt = ev.altKey; var alt = ev.altKey;
var shift = ev.shiftKey; var shift = ev.shiftKey;
var ctrl = ev.ctrlKey; var ctrl = e.getAccelKey();
var button = e.getButton(); var button = e.getButton();
if (!ctrl && !alt) { if (!ctrl && !alt) {
if (e.editor.selection.rangeCount > 1) { if (e.editor.inMultiSelectMode) {
if (button == 0) { if (button == 0) {
e.editor.exitMultiSelectMode(); e.editor.exitMultiSelectMode();
} else if (button == 2) { } else if (button == 2) {
@ -70,75 +70,20 @@ function onMouseDown(e) {
var editor = e.editor; var editor = e.editor;
var selection = editor.selection; var selection = editor.selection;
var isMultiSelect = selection.rangeCount > 1 var isMultiSelect = editor.inMultiSelectMode;
var pos = e.getDocumentPosition(); var pos = e.getDocumentPosition();
var rangeList = selection.rangeList;
var cursor = selection.getCursor() var cursor = selection.getCursor()
var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
if (ctrl && !shift && !alt && button == 0) {
if (!isMultiSelect && inSelection)
return // dragging
if (!isMultiSelect) {
selection.addRange(selection.toOrientedRange());
}
if (inSelection)
selection.clearSelection();
var helper = selection.toOrientedRange();
editor.addSelectionMarker(helper);
var oldRange = rangeList.rangeAtPoint(pos);
event.capture(editor.container, function(){}, function() {
editor.removeSelectionMarkers([helper]);
var tmpSel = selection.toOrientedRange();
if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) {
if (selection.rangeCount > 1) {
range = editor.selection.rangeList.substractPoint(tmpSel.cursor);
var range = editor.selection.rangeList.all[0];
if (range)
editor.selection.addRange(range);
return;
}
}
selection.addRange(tmpSel);
});
//e.stop()
} else if (!shift && alt && button == 0) {
e.stop()
var mouseX = e.pageX, mouseY = e.pageY; var mouseX = e.pageX, mouseY = e.pageY;
var clickX = mouseX, clickY = mouseY;
var onMouseSelection = function(e) { var onMouseSelection = function(e) {
mouseX = event.getDocumentX(e); mouseX = event.getDocumentX(e);
mouseY = event.getDocumentY(e); mouseY = event.getDocumentY(e);
}; };
if (isMultiSelect && !ctrl) { var blockSelect = function() {
selection.single();
}
selection.moveCursorToPosition(pos);
selection.clearSelection();
var rectSel = [];
var session = editor.session;
var onMouseSelectionEnd = function(e) {
clearInterval(timerId);
editor.removeSelectionMarkers(rectSel);
for (var i = 0; i < rectSel.length; i++)
selection.addRange(rectSel[i])
};
var anchor = selection.getCursor();
var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
var clippedAnchor = session.documentToScreenPosition(anchor);
var screenCursor = screenAnchor;
var onSelectionInterval = function() {
var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column); var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
@ -154,13 +99,103 @@ function onMouseDown(e) {
editor.removeSelectionMarkers(rectSel); editor.removeSelectionMarkers(rectSel);
rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
rectSel.forEach(editor.addSelectionMarker, editor); rectSel.forEach(editor.addSelectionMarker, editor);
editor.updateSelectionMarkers()
editor.renderer.updateCursor();
editor.renderer.updateBackMarkers();
}; };
var normalSelect = function() {
var clickSelection
if (_self.$clickSelection) {
if (_self.$clickSelection.contains(cursor.row, cursor.column)) {
editor.selection.setSelectionRange(_self.$clickSelection);
}
else {
if (_self.$clickSelection.compare(cursor.row, cursor.column) == -1) {
anchor = _self.$clickSelection.end;
}
else {
anchor = _self.$clickSelection.start;
}
editor.selection.setSelectionAnchor(anchor.row, anchor.column);
editor.selection.selectToPosition(cursor);
}
}
else {
editor.selection.selectToPosition(cursor);
}
editor.renderer.scrollCursorIntoView();
};
var session = editor.session;
var anchor = selection.getCursor();
var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
var clippedAnchor = session.documentToScreenPosition(anchor);
var screenCursor = screenAnchor;
onSelectionInterval = blockSelect;
if (ctrl && !shift && !alt && button == 0) {
if (!isMultiSelect && inSelection)
return // dragging
if (!isMultiSelect) {
selection.addRange(selection.toOrientedRange());
}
if (inSelection)
selection.clearSelection();
var helper = selection.toOrientedRange();
editor.addSelectionMarker(helper);
var oldRange = selection.rangeList.rangeAtPoint(pos);
event.capture(editor.container, function(){}, function() {
editor.removeSelectionMarkers([helper]);
var tmpSel = selection.toOrientedRange();
if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) {
if (selection.rangeCount > 1) {
editor.selection.substractPoint(tmpSel.cursor);
var range = editor.selection.ranges[0];
if (range)
editor.selection.addRange(range);
return;
}
}
selection.addRange(tmpSel);
});
//e.stop()
} else if (!shift && alt && button == 0) {
e.stop()
if (isMultiSelect && !ctrl) {
selection.toSingleRange();
} else if (!isMultiSelect && ctrl) {
selection.addRange();
}
selection.moveCursorToPosition(pos);
selection.clearSelection();
var rectSel = [];
var onMouseSelectionEnd = function(e) {
clearInterval(timerId);
editor.removeSelectionMarkers(rectSel);
for (var i = 0; i < rectSel.length; i++)
selection.addRange(rectSel[i])
};
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
var timerId = setInterval(onSelectionInterval, 20); var timerId = setInterval(function() {onSelectionInterval()}, 20);
return e.preventDefault(); return e.preventDefault();
} }

View file

@ -41,7 +41,7 @@ define(function(require, exports, module) {
var RangeList = require("./range_list").RangeList; var RangeList = require("./range_list").RangeList;
var Range = require("./range").Range; var Range = require("./range").Range;
var Selection = require("./selection").Selection; var Selection = require("./selection").Selection;
var onMouseDown = require("./mouse/multi_select_mouse_handler").onMouseDown; var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
exports.commands = require("./commands/multi_select_commands"); exports.commands = require("./commands/multi_select_commands");
// Todo // Todo
@ -65,49 +65,98 @@ var EditSession = require("./edit_session").EditSession;
// extend Selection // extend Selection
;(function() { ;(function() {
// list of ranges in reverse addition order
this.ranges = null;
// automatically sorted list of ranges
this.rangeList = null;
/**
* add a range to selection entering multiselect mode if necessary
*/
this.addRange = function(range) { this.addRange = function(range) {
if (!this.inMultiSelectMode && this.rangeCount == 0) {
var oldRange = this.toOrientedRange();
if (!range || !range.isEqual(oldRange)) {
this.rangeList.add(oldRange);
this.$onAddRange(oldRange);
}
}
if (!range)
return;
if (!range.cursor) if (!range.cursor)
range.cursor = range.end; range.cursor = range.end;
if (this.rangeCount == 0) { var removed = this.rangeList.add(range);
var oldRange = this.toOrientedRange();
this.rangeList.add(oldRange);
this._emit("addRange", {range: oldRange});
}
this.rangeList.add(range);
this.rangeCount = this.rangeList.ranges.length;
if (this.rangeCount > 1 && !this.inMultiSelectMode) {
this._emit("multiSelect");
this.inMultiSelectMode = true;
this.$undoSelect = false;
this.rangeList.attach(this.session);
}
this.fromOrientedRange(range); this.fromOrientedRange(range);
if (this.rangeCount >= 1) this.$onAddRange(range);
this._emit("addRange", {range: range});
if (removed.length)
this.$onRemoveRange(removed);
if (this.rangeCount > 0 && !this.inMultiSelectMode) {
this._emit("multiSelect");
this.inMultiSelectMode = true;
this.session.$undoSelect = false;
this.rangeList.attach(this.session);
}
}; };
this.single = function(range) { this.toSingleRange = function(range) {
range = range || this.rangeList.all[0]; range = range || this.ranges[0];
this.rangeList.removeAll(); var removed = this.rangeList.removeAll();
if (removed.length)
this.$onRemoveRange(removed);
range && this.fromOrientedRange(range); range && this.fromOrientedRange(range);
}; };
this.$onRemoveRange = function(e) { this.substractPoint = function(pos) {
this.rangeCount = this.rangeList.ranges.length; var removed = this.rangeList.substractPoint(pos);
this._emit("removeRange", e); if (removed) {
this.$onRemoveRange(removed);
return removed[0]
}
};
if (this.rangeCount <= 1 && this.inMultiSelectMode) { this.mergeOverlappingRanges = function() {
var removed = this.rangeList.merge();
var lastRange = this.ranges[0];
if (removed.length)
this.$onRemoveRange(removed);
if (lastRange)
this.fromOrientedRange(lastRange);
};
this.$onAddRange = function(range) {
this.rangeCount = this.rangeList.ranges.length;
this.ranges.unshift(range);
this._emit("addRange", {range: range});
};
this.$onRemoveRange = function(removed) {
this.rangeCount = this.rangeList.ranges.length;
if (this.rangeCount == 1 && this.inMultiSelectMode) {
removed.push(this.rangeList.ranges.pop());
this.rangeCount = 0;
}
for (var i = removed.length; i--; ) {
var index = this.ranges.indexOf(removed[i]);
this.ranges.splice(index, 1);
}
console.log(this.ranges+'')
this._emit("removeRange", {ranges: removed});
if (this.rangeCount == 0 && this.inMultiSelectMode) {
this.inMultiSelectMode = false; this.inMultiSelectMode = false;
this._emit("singleSelect"); this._emit("singleSelect");
this.$undoSelect = true; this.session.$undoSelect = true;
this.rangeList.detach(this.session); this.rangeList.detach(this.session);
if (this.rangeCount == 1)
this.single();
} }
}; };
@ -116,27 +165,11 @@ var EditSession = require("./edit_session").EditSession;
if (this.rangeList) if (this.rangeList)
return; return;
var rangeList = new RangeList; this.rangeList = new RangeList;
// list of ranges in reverse addition order this.ranges = [];
// rangeList.all[0] is the same as selection.getRange this.rangeCount = 0;
rangeList.all = [];
rangeList.on("add", function(e) {
rangeList.all.unshift(e.range)
})
rangeList.on("remove", function(e) {
var ranges = e.ranges
for (var i = ranges.length; i--; ) {
var index = rangeList.all.indexOf(ranges[i]);
rangeList.all.splice(index, 1);
}
});
this.rangeList = rangeList;
this.cursor = this.selectionLead;
this.rangeCount = 1;
this.rangeList.on("remove", this.$onRemoveRange.bind(this));
}; };
this.getAllRanges = function() { this.getAllRanges = function() {
return this.rangeList.ranges.concat() return this.rangeList.ranges.concat()
}; };
@ -147,7 +180,7 @@ var EditSession = require("./edit_session").EditSession;
var lastRange = ranges[ranges.length - 1] var lastRange = ranges[ranges.length - 1]
var range = Range.fromPoints(ranges[0].start, lastRange.end) var range = Range.fromPoints(ranges[0].start, lastRange.end)
this.single() this.toSingleRange()
this.setSelectionRange(range, lastRange.cursor == lastRange.start) this.setSelectionRange(range, lastRange.cursor == lastRange.start)
} else { } else {
var cursor = this.session.documentToScreenPosition(this.selectionLead); var cursor = this.session.documentToScreenPosition(this.selectionLead);
@ -158,6 +191,11 @@ var EditSession = require("./edit_session").EditSession;
} }
}; };
/**
* gets list of ranges composing rectangular block on the screen
* @includeEmptyLines if true includes ranges inside the block which
* are empty becuase of the clipping
*/
this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {
var rectSel = []; var rectSel = [];
@ -225,6 +263,11 @@ var EditSession = require("./edit_session").EditSession;
// extend Editor // extend Editor
var Editor = require("./editor").Editor; var Editor = require("./editor").Editor;
;(function() { ;(function() {
this.updateSelectionMarkers = function(orientedRange) {
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
this.addSelectionMarker = function(orientedRange) { this.addSelectionMarker = function(orientedRange) {
if (!orientedRange.cursor) if (!orientedRange.cursor)
orientedRange.cursor = orientedRange.end; orientedRange.cursor = orientedRange.end;
@ -234,7 +277,7 @@ var Editor = require("./editor").Editor;
this.session.$selectionMarkers.push(orientedRange); this.session.$selectionMarkers.push(orientedRange);
this.session.selectionMarkerCount = this.session.$selectionMarkers.length; this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
return orientedRange return orientedRange;
}; };
this.removeSelectionMarkers = function(ranges) { this.removeSelectionMarkers = function(ranges) {
@ -310,21 +353,16 @@ var Editor = require("./editor").Editor;
this.selection = session.selection = selection; this.selection = session.selection = selection;
this.inVirtualSelectionMode = false; this.inVirtualSelectionMode = false;
selection._eventRegistry = reg; selection._eventRegistry = reg;
rangeList.merge(); selection.mergeOverlappingRanges();
var lastRange = selection.rangeList.all[0] this.onCursorChange();
lastRange && selection.fromOrientedRange(lastRange); this.onSelectionChange();
selection._emit("changeSelection")
selection._emit("changeCursor")
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
}; };
this.exitMultiSelectMode = function() { this.exitMultiSelectMode = function() {
if (this.inVirtualSelectionMode) if (this.inVirtualSelectionMode)
return; return;
this.multiSelect.single(); this.multiSelect.toSingleRange();
}; };
// todo route copy/cut/paste through commandmanager // todo route copy/cut/paste through commandmanager
@ -393,19 +431,20 @@ var Editor = require("./editor").Editor;
} else { } else {
var allRanges = this.selection.rangeList.ranges; var allRanges = this.selection.rangeList.ranges;
// remove range if at end // remove range if at end
if (skip || range.isEequal(allRanges[dir == 1 ? 0 : allRanges.length - 1])) // var atEdge = range.isEqual(allRanges[dir == 1 ? 0 : allRanges.length - 1]);
if (skip)
var toRemove = range.cursor; var toRemove = range.cursor;
} }
this.selection.addRange(newRange); this.selection.addRange(newRange);
if (toRemove) if (toRemove)
this.selection.rangeList.substractPoint(toRemove); this.selection.substractPoint(toRemove);
} }
this.transposeSelections = function(dir) { this.transposeSelections = function(dir) {
var session = this.session; var session = this.session;
var sel = session.multiSelect; var sel = session.multiSelect;
var all = sel.rangeList.all; var all = sel.ranges;
var words = []; var words = [];
for (var i = all.length; i--; ) { for (var i = all.length; i--; ) {
@ -437,7 +476,7 @@ var Editor = require("./editor").Editor;
this.selectMore = function (dir, skip) { this.selectMore = function (dir, skip) {
var session = this.session; var session = this.session;
var sel = session.multiSelect; var sel = session.multiSelect;
var all = sel.rangeList.all; var all = sel.ranges;
var range = sel.toOrientedRange(); var range = sel.toOrientedRange();
if (range.isEmpty()) { if (range.isEmpty()) {
@ -454,7 +493,7 @@ var Editor = require("./editor").Editor;
this.multiSelect.addRange(newRange); this.multiSelect.addRange(newRange);
} }
if (skip) if (skip)
this.multiSelect.rangeList.substractPoint(range.cursor); this.multiSelect.substractPoint(range.cursor);
} }
@ -519,6 +558,8 @@ exports.onSessionChange = function(e) {
session.multiSelect.on("multiSelect", this.$onMultiSelect); session.multiSelect.on("multiSelect", this.$onMultiSelect);
session.multiSelect.on("singleSelect", this.$onSingleSelect); session.multiSelect.on("singleSelect", this.$onSingleSelect);
// this.$onSelectionChange = this.onSelectionChange.bind(this);
if (this.inMultiSelectMode != session.selection.inMultiSelectMode) { if (this.inMultiSelectMode != session.selection.inMultiSelectMode) {
if (session.selection.inMultiSelectMode) if (session.selection.inMultiSelectMode)
this.$onMultiSelect(); this.$onMultiSelect();

View file

@ -46,8 +46,6 @@ var RangeList = function(startRow, startColumn, endRow, endColumn) {
}; };
(function() { (function() {
oop.implement(this, EventEmitter);
this.comparePoints = function(p1, p2) { this.comparePoints = function(p1, p2) {
return p1.row - p2.row || p1.column - p2.column return p1.row - p2.row || p1.column - p2.column
}; };
@ -84,25 +82,22 @@ var RangeList = function(startRow, startColumn, endRow, endColumn) {
else else
endIndex++; endIndex++;
var removed = this.ranges.splice(startIndex, endIndex - startIndex, range); return this.ranges.splice(startIndex, endIndex - startIndex, range);
if (removed.length)
this._emit("remove", {ranges: removed});
this._emit("add", {range: range});
return startIndex;
}; };
this.addList = function(list) { this.addList = function(list) {
list.forEach(this.add, this); var removed = [];
for (var i = list.length; i--; ) {
removed.push.call(removed, this.add(list[i]))
}
return removed;
}; };
this.substractPoint = function(pos) { this.substractPoint = function(pos) {
var i = this.pointIndex(pos); var i = this.pointIndex(pos);
if (i >= 0) { if (i >= 0)
var removed = this.ranges.splice(i, 1); return this.ranges.splice(i, 1);
this._emit("remove", {ranges: removed});
return removed[0]
}
}; };
// merge overlapping ranges // merge overlapping ranges
@ -131,8 +126,7 @@ var RangeList = function(startRow, startColumn, endRow, endColumn) {
i--; i--;
} }
if (removed.length) return removed;
this._emit("remove", {ranges: removed});
}; };
this.contains = function(row, column) { this.contains = function(row, column) {
@ -170,8 +164,7 @@ var RangeList = function(startRow, startColumn, endRow, endColumn) {
}; };
this.removeAll = function() { this.removeAll = function() {
if (this.ranges.length) return this.ranges.splice(0, this.ranges.length);
this._emit("remove", {ranges: this.ranges.splice(0, this.ranges.length)});
}; };
this.attach = function(session) { this.attach = function(session) {

View file

@ -124,25 +124,24 @@ module.exports = {
new Range(8,8,9,9) new Range(8,8,9,9)
]); ]);
var removed = []; var removed = [];
rangeList.on('remove', function(e) {removed = e.ranges});
assert.equal(rangeList.ranges.length, 4); assert.equal(rangeList.ranges.length, 4);
rangeList.ranges[1].end.row = 7; rangeList.ranges[1].end.row = 7;
rangeList.merge(); removed = rangeList.merge();
assert.equal(removed.length, 1); assert.equal(removed.length, 1);
assert.range(rangeList.ranges[1], 4,2,7,7); assert.range(rangeList.ranges[1], 4,2,7,7);
assert.equal(rangeList.ranges.length, 3); assert.equal(rangeList.ranges.length, 3);
rangeList.ranges[0].end.row = 10; rangeList.ranges[0].end.row = 10;
rangeList.merge(); removed = rangeList.merge();
assert.range(rangeList.ranges[0], 1,2,10,4); assert.range(rangeList.ranges[0], 1,2,10,4);
assert.equal(removed.length, 2); assert.equal(removed.length, 2);
assert.equal(rangeList.ranges.length, 1); assert.equal(rangeList.ranges.length, 1);
rangeList.ranges.push(new Range(10,10,10,10)); rangeList.ranges.push(new Range(10,10,10,10));
rangeList.ranges.push(new Range(10,10,10,10)); rangeList.ranges.push(new Range(10,10,10,10));
rangeList.merge(); removed = rangeList.merge();
assert.equal(rangeList.ranges.length, 2); assert.equal(rangeList.ranges.length, 2);
}, },