proper shift selection in list

This commit is contained in:
Joao Moreno
2017-03-22 12:05:23 +01:00
parent 08d63ac296
commit 54c463d20f

View File

@@ -6,6 +6,7 @@
import 'vs/css!./list';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { isNumber } from 'vs/base/common/types';
import { range } from 'vs/base/common/arrays';
import { memoize } from 'vs/base/common/decorators';
import * as DOM from 'vs/base/browser/dom';
import * as platform from 'vs/base/common/platform';
@@ -282,6 +283,28 @@ class MouseController<T> implements IDisposable {
this.view.domNode.focus();
const focus = e.index;
if (e.shiftKey) {
const oldFocus = this.list.getFocus()[0];
if (oldFocus !== undefined) {
const min = Math.min(oldFocus, focus);
const max = Math.max(oldFocus, focus);
const rangeSelection = range(max + 1, min);
const selection = this.list.getSelection();
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [oldFocus]), oldFocus);
if (contiguousRange.length === 0) {
return;
}
const newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange));
this.list.setSelection(newSelection);
}
return;
}
this.list.setFocus([focus]);
if (platform.isMacintosh ? e.altKey : e.ctrlKey) {
@@ -316,6 +339,56 @@ const DefaultOptions: IListOptions<any> = {
mouseSupport: true
};
function getContiguousRangeContaining(range: number[], value: number): number[] {
const index = range.indexOf(value);
if (index === -1) {
return [];
}
const result = [];
let i = index - 1;
while (i >= 0 && range[i] === value - (index - i)) {
result.push(range[i--]);
}
result.reverse();
i = index;
while (i < range.length && range[i] === value + (i - index)) {
result.push(range[i++]);
}
return result;
}
/**
* Given two sorted collections of numbers, returns the intersection
* betweem them (OR).
*/
function disjunction(one: number[], other: number[]): number[] {
const result = [];
let i = 0, j = 0;
while (i < one.length || j < other.length) {
if (i >= one.length) {
result.push(other[j++]);
} else if (j >= other.length) {
result.push(one[i++]);
} else if (one[i] === other[j]) {
result.push(one[i]);
i++;
j++;
continue;
} else if (one[i] < other[j]) {
result.push(one[i++]);
} else {
result.push(other[j++]);
}
}
return result;
}
/**
* Given two sorted collections of numbers, returns the exclusive
* disjunction between them (XOR).
@@ -343,6 +416,33 @@ function exclusiveDisjunction(one: number[], other: number[]): number[] {
return result;
}
/**
* Given two sorted collections of numbers, returns the relative
* complement between them (XOR).
*/
function relativeComplement(one: number[], other: number[]): number[] {
const result = [];
let i = 0, j = 0;
while (i < one.length || j < other.length) {
if (i >= one.length) {
result.push(other[j++]);
} else if (j >= other.length) {
result.push(one[i++]);
} else if (one[i] === other[j]) {
i++;
j++;
continue;
} else if (one[i] < other[j]) {
result.push(one[i++]);
} else {
j++;
}
}
return result;
}
const numericSort = (a: number, b: number) => a - b;
export class List<T> implements ISpliceable<T>, IDisposable {