@@ -3,6 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// Work variables to avoid garbage collection.
|
||||
let i = 0;
|
||||
|
||||
/**
|
||||
* A generic list that is maintained in sorted order and allows values with duplicate keys. This
|
||||
* list is based on binary search and as such locating a key will take O(log n) amortized, this
|
||||
@@ -25,7 +28,7 @@ export class SortedList<T> {
|
||||
this._array.push(value);
|
||||
return;
|
||||
}
|
||||
const i = this._search(this._getKey(value), 0, this._array.length - 1);
|
||||
i = this._search(this._getKey(value), 0, this._array.length - 1);
|
||||
this._array.splice(i, 0, value);
|
||||
}
|
||||
|
||||
@@ -37,7 +40,7 @@ export class SortedList<T> {
|
||||
if (key === undefined) {
|
||||
return false;
|
||||
}
|
||||
let i = this._search(key, 0, this._array.length - 1);
|
||||
i = this._search(key, 0, this._array.length - 1);
|
||||
if (i === -1) {
|
||||
return false;
|
||||
}
|
||||
@@ -57,7 +60,7 @@ export class SortedList<T> {
|
||||
if (this._array.length === 0) {
|
||||
return;
|
||||
}
|
||||
let i = this._search(key, 0, this._array.length - 1);
|
||||
i = this._search(key, 0, this._array.length - 1);
|
||||
if (i < 0 || i >= this._array.length) {
|
||||
return;
|
||||
}
|
||||
@@ -69,6 +72,22 @@ export class SortedList<T> {
|
||||
} while (++i < this._array.length && this._getKey(this._array[i]) === key);
|
||||
}
|
||||
|
||||
public forEachByKey(key: number, callback: (value: T) => void): void {
|
||||
if (this._array.length === 0) {
|
||||
return;
|
||||
}
|
||||
i = this._search(key, 0, this._array.length - 1);
|
||||
if (i < 0 || i >= this._array.length) {
|
||||
return;
|
||||
}
|
||||
if (this._getKey(this._array[i]) !== key) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
callback(this._array[i]);
|
||||
} while (++i < this._array.length && this._getKey(this._array[i]) === key);
|
||||
}
|
||||
|
||||
public values(): IterableIterator<T> {
|
||||
return this._array.values();
|
||||
}
|
||||
|
||||
@@ -163,5 +163,6 @@ export class MockDecorationService implements IDecorationService {
|
||||
public reset(): void { }
|
||||
public *getDecorationsAtLine(line: number): IterableIterator<IInternalDecoration> { }
|
||||
public *getDecorationsAtCell(x: number, line: number): IterableIterator<IInternalDecoration> { }
|
||||
public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void { }
|
||||
public dispose(): void { }
|
||||
}
|
||||
|
||||
@@ -11,6 +11,12 @@ import { SortedList } from 'common/SortedList';
|
||||
import { IColor } from 'common/Types';
|
||||
import { IDecorationOptions, IDecoration, IMarker, IEvent } from 'xterm';
|
||||
|
||||
/** Work variables to avoid garbage collection. */
|
||||
const w = {
|
||||
xmin: 0,
|
||||
xmax: 0
|
||||
};
|
||||
|
||||
export class DecorationService extends Disposable implements IDecorationService {
|
||||
public serviceBrand: any;
|
||||
|
||||
@@ -72,6 +78,16 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
}
|
||||
}
|
||||
|
||||
public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void {
|
||||
this._decorations.forEachByKey(line, d => {
|
||||
w.xmin = d.options.x ?? 0;
|
||||
w.xmax = w.xmin + (d.options.width ?? 1);
|
||||
if (x >= w.xmin && x < w.xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
|
||||
callback(d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
for (const d of this._decorations.values()) {
|
||||
this._onDecorationRemoved.fire(d);
|
||||
|
||||
@@ -308,6 +308,11 @@ export interface IDecorationService extends IDisposable {
|
||||
getDecorationsAtLine(line: number): IterableIterator<IInternalDecoration>;
|
||||
/** Iterates over the decorations at a cell (in no particular order). */
|
||||
getDecorationsAtCell(x: number, line: number, layer?: 'bottom' | 'top'): IterableIterator<IInternalDecoration>;
|
||||
/**
|
||||
* Trigger a callback over the decoration at a cell (in no particular order). This is a high
|
||||
* performance, but less ergonomic, version of {@link getDecorationsAtCell}.
|
||||
*/
|
||||
forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void;
|
||||
}
|
||||
export interface IInternalDecoration extends IDecoration {
|
||||
readonly options: IDecorationOptions;
|
||||
|
||||
Reference in New Issue
Block a user