-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(layered-storage): add a new storage for options
This is intended to replace the prototype plus hacks insanity used at the moment. However this is still WIP. There is no documentations yet and more testing is necessary. TODO: - Add off. - Write docs. - Probably some other things too. In a quick test I was able to resolve the issue discussed in visjs/vis-network#178 and visjs/vis-network#213 with just a few lines of code. Which is much better than the massive mess of weird hacks that doesn't work reliably anyway. Putting this to use will be a lot of work but fortunately it should be possible to do it in parts. I would first use this in LayoutEngine and EdgesHandler to resolve the forementioned issues and then probably one module at the time. Features: - Encapsulates options merging. - Explicit layer/segment/key structure instead of prototype chains. - Observable. - Overrides. * - Type safety in TypeScript. * Hierarchical layout is incompatible with smooth edges and has to disable them. Overrides combined with observing easily and elegently solve that. See the forementioned issues for current state.
- Loading branch information
Showing
19 changed files
with
1,567 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type KeyRange = number | string | symbol; | ||
export type KeyValueLookup = Record<KeyRange, any>; | ||
export type LayerRange = number; | ||
export type Segment = boolean | number | object | string | symbol; | ||
|
||
export type EventCallback<Key> = (keys: Key[]) => void; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { KeyValueLookup, LayerRange, Segment } from "./common"; | ||
|
||
const reverseNumeric = (a: number, b: number): number => b - a; | ||
|
||
export class LayeredStorageCore< | ||
KeyValue extends KeyValueLookup, | ||
Layer extends LayerRange | ||
> { | ||
public monolithic = Symbol("Monolithic"); | ||
|
||
private _data = new Map< | ||
Layer, | ||
Map<Segment, Map<keyof KeyValue, KeyValue[keyof KeyValue]>> | ||
>(); | ||
|
||
private _layers: Layer[] = []; | ||
private readonly _segments = new Set<Segment>(); | ||
|
||
private readonly _topLevelCache = new Map< | ||
Segment, | ||
Map<keyof KeyValue, KeyValue[keyof KeyValue]> | ||
>(); | ||
|
||
private _updateCache(key: keyof KeyValue): void { | ||
segmentsLoop: for (const segment of this._segments) { | ||
const sCache = | ||
this._topLevelCache.get(segment) || | ||
this._topLevelCache.set(segment, new Map()).get(segment)!; | ||
|
||
sCache.delete(key); | ||
|
||
for (const layer of this._layers) { | ||
const lsData = this._getLSData(layer, segment); | ||
if (lsData.has(key)) { | ||
sCache.set(key, lsData.get(key)!); | ||
continue segmentsLoop; | ||
} | ||
|
||
const lmData = this._getLSData(layer, this.monolithic); | ||
if (lmData.has(key)) { | ||
sCache.set(key, lmData.get(key)!); | ||
continue segmentsLoop; | ||
} | ||
} | ||
} | ||
} | ||
|
||
private _getLSData( | ||
layer: Layer, | ||
segment: Segment | ||
): Map<keyof KeyValue, KeyValue[keyof KeyValue]> { | ||
let lData = this._data.get(layer); | ||
if (lData == null) { | ||
lData = new Map(); | ||
this._data.set(layer, lData); | ||
|
||
this._layers = [...this._data.keys()].sort(reverseNumeric); | ||
} | ||
|
||
let lsData = lData.get(segment); | ||
if (lsData == null) { | ||
lsData = new Map(); | ||
lData.set(segment, lsData); | ||
|
||
this._segments.add(segment); | ||
} | ||
|
||
return lsData; | ||
} | ||
|
||
public get<Key extends keyof KeyValue>( | ||
segment: Segment, | ||
key: Key | ||
): KeyValue[Key] | undefined { | ||
const sData = this._topLevelCache.get(segment); | ||
if (sData == null) { | ||
return; | ||
} | ||
|
||
return sData.get(key); | ||
} | ||
|
||
public has<Key extends keyof KeyValue>(segment: Segment, key: Key): boolean { | ||
const sData = this._topLevelCache.get(segment); | ||
if (sData == null) { | ||
return false; | ||
} | ||
|
||
return sData.has(key); | ||
} | ||
|
||
public set<Key extends keyof KeyValue>( | ||
layer: Layer, | ||
segment: Segment, | ||
key: Key, | ||
value: KeyValue[Key] | ||
): void { | ||
const lsData = this._getLSData(layer, segment); | ||
lsData.set(key, value); | ||
|
||
this._updateCache(key); | ||
} | ||
|
||
public delete<Key extends keyof KeyValue>( | ||
layer: Layer, | ||
segment: Segment, | ||
key: Key | ||
): boolean { | ||
const lsData = this._getLSData(layer, segment); | ||
const didItExist = lsData.delete(key); | ||
|
||
this._updateCache(key); | ||
|
||
return didItExist; | ||
} | ||
|
||
public deleteSegmentData(segment: Segment): void { | ||
for (const lData of this._data.values()) { | ||
lData.delete(segment); | ||
} | ||
this._topLevelCache.delete(segment); | ||
this._segments.delete(segment); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export { | ||
LayeredStorage, | ||
LayeredStorageSegmentTransaction, | ||
LayeredStorageTransaction | ||
} from "./layered-storage"; | ||
export { LayeredStorageSegment } from "./segment"; | ||
export { EventCallback, KeyValueLookup, LayerRange, Segment } from "./common"; |
Oops, something went wrong.