Maintain decorations sorted by line

This commit is contained in:
Daniel Imms
2022-05-11 09:34:51 -07:00
parent c0b4edaf31
commit 931ee9e89e
3 changed files with 207 additions and 25 deletions
+22 -25
View File
@@ -7,13 +7,19 @@ import { css } from 'common/Color';
import { EventEmitter } from 'common/EventEmitter';
import { Disposable } from 'common/Lifecycle';
import { IDecorationService, IInternalDecoration } from 'common/services/Services';
import { SortedList } from 'common/SortedList';
import { IColor } from 'common/Types';
import { IDecorationOptions, IDecoration, IMarker, IEvent } from 'xterm';
export class DecorationService extends Disposable implements IDecorationService {
public serviceBrand: any;
private readonly _decorations: IInternalDecoration[] = [];
/**
* A list of all decorations, sorted by the marker's line value. This relies on the fact that
* while marker line values do change, they should all change by the same amount so this should
* never become out of order.
*/
private readonly _decorations: SortedList<IInternalDecoration> = new SortedList(e => e.marker.line);
private _onDecorationRegistered = this.register(new EventEmitter<IInternalDecoration>());
public get onDecorationRegistered(): IEvent<IInternalDecoration> { return this._onDecorationRegistered.event; }
@@ -35,56 +41,47 @@ export class DecorationService extends Disposable implements IDecorationService
const markerDispose = decoration.marker.onDispose(() => decoration.dispose());
decoration.onDispose(() => {
if (decoration) {
const index = this._decorations.indexOf(decoration);
if (index >= 0) {
this._decorations.splice(this._decorations.indexOf(decoration), 1);
if (this._decorations.delete(decoration)) {
this._onDecorationRemoved.fire(decoration);
}
markerDispose.dispose();
}
});
this._decorations.push(decoration);
this._decorations.insert(decoration);
this._onDecorationRegistered.fire(decoration);
}
return decoration;
}
public reset(): void {
for (let i = 0; i < this._decorations.length; i++) {
this._decorations[0].dispose();
for (const d of this._decorations.values()) {
d.dispose();
}
this._decorations.length = 0;
this._decorations.clear();
}
public *getDecorationsAtLine(line: number): IterableIterator<IInternalDecoration> {
// TODO: This could be made much faster if _decorations was sorted by line (and col?)
for (const d of this.decorations) {
if (d.marker.line === line) {
yield d;
}
}
return this._decorations.getKeyIterator(line);
}
public *getDecorationsAtCell(x: number, line: number): IterableIterator<IInternalDecoration> {
let xmin = 0;
let xmax = 0;
for (const d of this.decorations) {
if (d.marker.line === line) {
xmin = d.options.x ?? 0;
xmax = xmin + (d.options.width ?? 1);
if (x >= xmin && x < xmax) {
yield d;
}
for (const d of this._decorations.getKeyIterator(line)) {
console.log('d', d);
xmin = d.options.x ?? 0;
xmax = xmin + (d.options.width ?? 1);
if (x >= xmin && x < xmax) {
yield d;
}
}
}
public dispose(): void {
for (const decoration of this._decorations) {
this._onDecorationRemoved.fire(decoration);
decoration.dispose();
for (const d of this._decorations.values()) {
this._onDecorationRemoved.fire(d);
}
this._decorations.length = 0;
this.reset();
}
}