From 100418b8fc7216927680541c224beaef717defad Mon Sep 17 00:00:00 2001 From: Patrick Tasse Date: Wed, 27 Apr 2022 11:19:55 -0400 Subject: [PATCH] Fix use of TimeGraphArrow sourceId and destinationId The sourceId and destinationId should be the row id of source row and destination row. But it is used as the index of the source and destination rows in the full list of rows. Change to use the sourceId and destinationId properly. This requires that the TimeGraphChartArrows layer receive the full list of row ids. Enable unit tests in build pipeline. Signed-off-by: Patrick Tasse --- .github/workflows/ci-cd.yml | 5 + example/src/index.ts | 2 +- example/src/test-data-provider.ts | 8 + .../time-graph-arrow.test.ts.snap | 1054 ++++++++++++++++- .../__tests__/time-graph-arrow.test.ts | 4 +- .../src/layer/time-graph-chart-arrows.ts | 27 +- 6 files changed, 1086 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index c128e684..1d6c293a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -39,6 +39,11 @@ jobs: NODE_OPTIONS: "--max_old_space_size=4096" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 + - name: Test + shell: bash + run: | + yarn test + publish: needs: build if: github.ref == 'refs/heads/master' && github.event_name == 'push' && github.repository == 'eclipse-cdt-cloud/timeline-chart' diff --git a/example/src/index.ts b/example/src/index.ts index 321690ca..5a4ebf0d 100644 --- a/example/src/index.ts +++ b/example/src/index.ts @@ -175,7 +175,7 @@ timeGraphChart.registerMouseInteractions({ } }); -timeGraphChartArrows.addArrows(timeGraph.arrows); +timeGraphChartArrows.addArrows(timeGraph.arrows, testDataProvider.getRowIds()); timeGraphChartRangeEvents.addRangeEvents(timeGraph.rangeEvents); const cursorReset = document.getElementById('cursor-reset'); diff --git a/example/src/test-data-provider.ts b/example/src/test-data-provider.ts index a537bb6b..9ba6ed06 100644 --- a/example/src/test-data-provider.ts +++ b/example/src/test-data-provider.ts @@ -181,6 +181,14 @@ export class TestDataProvider { }) } + getRowIds(): number[] { + const rowIds: number[] = []; + timeGraphEntries.model.entries.forEach(entry => { + rowIds.push(entry.id); + }); + return rowIds; + } + getData(opts: { range?: TimelineChart.TimeGraphRange, resolution?: number }): TimelineChart.TimeGraphModel { const rows: TimelineChart.TimeGraphRowModel[] = []; const range = opts.range || { start: BigInt(0), end: this.totalLength }; diff --git a/timeline-chart/src/components/__tests__/__snapshots__/time-graph-arrow.test.ts.snap b/timeline-chart/src/components/__tests__/__snapshots__/time-graph-arrow.test.ts.snap index e3258992..4b519e34 100644 --- a/timeline-chart/src/components/__tests__/__snapshots__/time-graph-arrow.test.ts.snap +++ b/timeline-chart/src/components/__tests__/__snapshots__/time-graph-arrow.test.ts.snap @@ -11,7 +11,7 @@ TimeGraphArrowComponent { "rect": null, "updateID": -1, }, - "_boundsID": 0, + "_boundsID": 1, "_boundsRect": null, "_destroyed": false, "_enabledFilters": null, @@ -448,7 +448,529 @@ TimeGraphArrowComponent { "batchDirty": -1, "batchTint": -1, "batches": Array [], - "children": Array [], + "children": Array [ + Graphics { + "_bounds": Bounds { + "maxX": -Infinity, + "maxY": -Infinity, + "minX": Infinity, + "minY": Infinity, + "rect": null, + "updateID": -1, + }, + "_boundsID": 0, + "_boundsRect": null, + "_destroyed": false, + "_enabledFilters": null, + "_events": Object {}, + "_eventsCount": 0, + "_fillStyle": FillStyle { + "alpha": 1, + "color": 16777215, + "matrix": null, + "texture": Texture { + "_events": Object {}, + "_eventsCount": 0, + "_frame": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "_rotate": 0, + "_updateID": 1, + "_uvs": TextureUvs { + "uvsFloat32": Float32Array [ + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + ], + "x0": 0, + "x1": 1, + "x2": 1, + "x3": 0, + "y0": 0, + "y1": 0, + "y2": 1, + "y3": 1, + }, + "baseTexture": BaseTexture { + "_batchEnabled": 0, + "_batchLocation": 0, + "_events": Object { + "update": EE { + "context": [Circular], + "fn": [Function], + "once": false, + }, + }, + "_eventsCount": 1, + "_glTextures": Object {}, + "alphaMode": 1, + "anisotropicLevel": 0, + "cacheId": null, + "destroy": [Function], + "destroyed": false, + "dirtyId": 0, + "dirtyStyleId": 0, + "emit": [Function], + "format": 6408, + "height": 16, + "isPowerOfTwo": true, + "mipmap": 1, + "on": [Function], + "once": [Function], + "parentTextureArray": null, + "resolution": 1, + "resource": CanvasResource { + "_height": 16, + "_width": 16, + "destroyed": false, + "internal": false, + "noSubImage": false, + "onError": Runner { + "_aliasCount": 0, + "_name": "onError", + "items": Array [ + [Circular], + ], + }, + "onResize": Runner { + "_aliasCount": 0, + "_name": "setRealSize", + "items": Array [ + [Circular], + ], + }, + "onUpdate": Runner { + "_aliasCount": 0, + "_name": "update", + "items": Array [ + [Circular], + ], + }, + "source": , + }, + "scaleMode": 1, + "target": 3553, + "textureCacheIds": Array [], + "touched": 0, + "type": 5121, + "uid": 2, + "valid": true, + "width": 16, + "wrapMode": 33071, + }, + "defaultAnchor": Point { + "x": 0, + "y": 0, + }, + "destroy": [Function], + "emit": [Function], + "noFrame": true, + "on": [Function], + "once": [Function], + "orig": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "textureCacheIds": Array [], + "trim": undefined, + "uvMatrix": null, + "valid": true, + }, + "visible": false, + }, + "_geometry": GraphicsGeometry { + "_bounds": Bounds { + "maxX": -Infinity, + "maxY": -Infinity, + "minX": Infinity, + "minY": Infinity, + "rect": null, + "updateID": -1, + }, + "_buffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 2, + "index": false, + "static": false, + }, + "_indexBuffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 3, + "index": true, + "static": false, + }, + "attributes": Object { + "aColor": Attribute { + "buffer": 0, + "instance": false, + "normalized": true, + "size": 4, + "start": undefined, + "stride": undefined, + "type": 5121, + }, + "aTextureCoord": Attribute { + "buffer": 0, + "instance": false, + "normalized": false, + "size": 2, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + "aTextureId": Attribute { + "buffer": 0, + "instance": false, + "normalized": true, + "size": 1, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + "aVertexPosition": Attribute { + "buffer": 0, + "instance": false, + "normalized": false, + "size": 2, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + }, + "batchDirty": -1, + "batchable": false, + "batches": Array [], + "boundsDirty": -1, + "boundsPadding": 0, + "buffers": Array [ + Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 2, + "index": false, + "static": false, + }, + Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 3, + "index": true, + "static": false, + }, + ], + "cacheDirty": -1, + "clearDirty": 0, + "closePointEps": 0.0001, + "colors": Array [], + "dirty": 0, + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeGeometry", + "items": Array [], + }, + "drawCalls": Array [], + "glVertexArrayObjects": Object {}, + "graphicsData": Array [], + "id": 1, + "indexBuffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 3, + "index": true, + "static": false, + }, + "indices": Array [], + "indicesUint16": null, + "instanceCount": 1, + "instanced": false, + "points": Array [], + "refCount": 1, + "shapeIndex": 0, + "textureIds": Array [], + "uvs": Array [], + "uvsFloat32": null, + }, + "_holeMode": false, + "_lastSortedIndex": 0, + "_lineStyle": LineStyle { + "alignment": 0.5, + "alpha": 1, + "cap": "butt", + "color": 0, + "join": "miter", + "matrix": null, + "miterLimit": 10, + "native": false, + "texture": Texture { + "_events": Object {}, + "_eventsCount": 0, + "_frame": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "_rotate": 0, + "_updateID": 1, + "_uvs": TextureUvs { + "uvsFloat32": Float32Array [ + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + ], + "x0": 0, + "x1": 1, + "x2": 1, + "x3": 0, + "y0": 0, + "y1": 0, + "y2": 1, + "y3": 1, + }, + "baseTexture": BaseTexture { + "_batchEnabled": 0, + "_batchLocation": 0, + "_events": Object { + "update": EE { + "context": [Circular], + "fn": [Function], + "once": false, + }, + }, + "_eventsCount": 1, + "_glTextures": Object {}, + "alphaMode": 1, + "anisotropicLevel": 0, + "cacheId": null, + "destroy": [Function], + "destroyed": false, + "dirtyId": 0, + "dirtyStyleId": 0, + "emit": [Function], + "format": 6408, + "height": 16, + "isPowerOfTwo": true, + "mipmap": 1, + "on": [Function], + "once": [Function], + "parentTextureArray": null, + "resolution": 1, + "resource": CanvasResource { + "_height": 16, + "_width": 16, + "destroyed": false, + "internal": false, + "noSubImage": false, + "onError": Runner { + "_aliasCount": 0, + "_name": "onError", + "items": Array [ + [Circular], + ], + }, + "onResize": Runner { + "_aliasCount": 0, + "_name": "setRealSize", + "items": Array [ + [Circular], + ], + }, + "onUpdate": Runner { + "_aliasCount": 0, + "_name": "update", + "items": Array [ + [Circular], + ], + }, + "source": , + }, + "scaleMode": 1, + "target": 3553, + "textureCacheIds": Array [], + "touched": 0, + "type": 5121, + "uid": 2, + "valid": true, + "width": 16, + "wrapMode": 33071, + }, + "defaultAnchor": Point { + "x": 0, + "y": 0, + }, + "destroy": [Function], + "emit": [Function], + "noFrame": true, + "on": [Function], + "once": [Function], + "orig": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "textureCacheIds": Array [], + "trim": undefined, + "uvMatrix": null, + "valid": true, + }, + "visible": false, + "width": 0, + }, + "_localBounds": null, + "_localBoundsRect": null, + "_mask": null, + "_matrix": null, + "_tint": 16777215, + "_transformID": -1, + "_zIndex": 0, + "alpha": 1, + "batchDirty": -1, + "batchTint": -1, + "batches": Array [], + "children": Array [], + "currentPath": null, + "filterArea": null, + "filters": null, + "isMask": false, + "isSprite": false, + "parent": [Circular], + "pluginName": "batch", + "renderable": true, + "shader": null, + "sortDirty": false, + "sortableChildren": false, + "state": State { + "_blendMode": 0, + "_polygonOffset": 0, + "data": 1, + }, + "tempDisplayObjectParent": null, + "transform": Transform { + "_currentLocalID": 0, + "_cx": 1, + "_cy": 0, + "_localID": 0, + "_parentID": -1, + "_rotation": 0, + "_sx": 0, + "_sy": 1, + "_worldID": 0, + "localTransform": Matrix { + "a": 1, + "array": null, + "b": 0, + "c": 0, + "d": 1, + "tx": 0, + "ty": 0, + }, + "pivot": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "position": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "scale": ObservablePoint { + "_x": 1, + "_y": 1, + "cb": [Function], + "scope": [Circular], + }, + "skew": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "worldTransform": Matrix { + "a": 1, + "array": null, + "b": 0, + "c": 0, + "d": 1, + "tx": 0, + "ty": 0, + }, + }, + "vertexData": null, + "visible": true, + "worldAlpha": 1, + }, + ], "currentPath": null, "filterArea": null, "filters": null, @@ -458,7 +980,7 @@ TimeGraphArrowComponent { "pluginName": "batch", "renderable": true, "shader": null, - "sortDirty": false, + "sortDirty": true, "sortableChildren": false, "state": State { "_blendMode": 0, @@ -994,7 +1516,529 @@ TimeGraphArrowComponent { "filters": null, "isMask": false, "isSprite": false, - "parent": null, + "parent": Graphics { + "_bounds": Bounds { + "maxX": -Infinity, + "maxY": -Infinity, + "minX": Infinity, + "minY": Infinity, + "rect": null, + "updateID": -1, + }, + "_boundsID": 1, + "_boundsRect": null, + "_destroyed": false, + "_enabledFilters": null, + "_events": Object {}, + "_eventsCount": 0, + "_fillStyle": FillStyle { + "alpha": 1, + "color": 16777215, + "matrix": null, + "texture": Texture { + "_events": Object {}, + "_eventsCount": 0, + "_frame": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "_rotate": 0, + "_updateID": 1, + "_uvs": TextureUvs { + "uvsFloat32": Float32Array [ + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + ], + "x0": 0, + "x1": 1, + "x2": 1, + "x3": 0, + "y0": 0, + "y1": 0, + "y2": 1, + "y3": 1, + }, + "baseTexture": BaseTexture { + "_batchEnabled": 0, + "_batchLocation": 0, + "_events": Object { + "update": EE { + "context": [Circular], + "fn": [Function], + "once": false, + }, + }, + "_eventsCount": 1, + "_glTextures": Object {}, + "alphaMode": 1, + "anisotropicLevel": 0, + "cacheId": null, + "destroy": [Function], + "destroyed": false, + "dirtyId": 0, + "dirtyStyleId": 0, + "emit": [Function], + "format": 6408, + "height": 16, + "isPowerOfTwo": true, + "mipmap": 1, + "on": [Function], + "once": [Function], + "parentTextureArray": null, + "resolution": 1, + "resource": CanvasResource { + "_height": 16, + "_width": 16, + "destroyed": false, + "internal": false, + "noSubImage": false, + "onError": Runner { + "_aliasCount": 0, + "_name": "onError", + "items": Array [ + [Circular], + ], + }, + "onResize": Runner { + "_aliasCount": 0, + "_name": "setRealSize", + "items": Array [ + [Circular], + ], + }, + "onUpdate": Runner { + "_aliasCount": 0, + "_name": "update", + "items": Array [ + [Circular], + ], + }, + "source": , + }, + "scaleMode": 1, + "target": 3553, + "textureCacheIds": Array [], + "touched": 0, + "type": 5121, + "uid": 2, + "valid": true, + "width": 16, + "wrapMode": 33071, + }, + "defaultAnchor": Point { + "x": 0, + "y": 0, + }, + "destroy": [Function], + "emit": [Function], + "noFrame": true, + "on": [Function], + "once": [Function], + "orig": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "textureCacheIds": Array [], + "trim": undefined, + "uvMatrix": null, + "valid": true, + }, + "visible": false, + }, + "_geometry": GraphicsGeometry { + "_bounds": Bounds { + "maxX": -Infinity, + "maxY": -Infinity, + "minX": Infinity, + "minY": Infinity, + "rect": null, + "updateID": -1, + }, + "_buffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 0, + "index": false, + "static": false, + }, + "_indexBuffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 1, + "index": true, + "static": false, + }, + "attributes": Object { + "aColor": Attribute { + "buffer": 0, + "instance": false, + "normalized": true, + "size": 4, + "start": undefined, + "stride": undefined, + "type": 5121, + }, + "aTextureCoord": Attribute { + "buffer": 0, + "instance": false, + "normalized": false, + "size": 2, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + "aTextureId": Attribute { + "buffer": 0, + "instance": false, + "normalized": true, + "size": 1, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + "aVertexPosition": Attribute { + "buffer": 0, + "instance": false, + "normalized": false, + "size": 2, + "start": undefined, + "stride": undefined, + "type": 5126, + }, + }, + "batchDirty": -1, + "batchable": false, + "batches": Array [], + "boundsDirty": -1, + "boundsPadding": 0, + "buffers": Array [ + Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 0, + "index": false, + "static": false, + }, + Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 1, + "index": true, + "static": false, + }, + ], + "cacheDirty": -1, + "clearDirty": 0, + "closePointEps": 0.0001, + "colors": Array [], + "dirty": 0, + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeGeometry", + "items": Array [], + }, + "drawCalls": Array [], + "glVertexArrayObjects": Object {}, + "graphicsData": Array [], + "id": 0, + "indexBuffer": Buffer { + "_glBuffers": Object {}, + "_updateID": 0, + "data": Float32Array [ + 0, + ], + "disposeRunner": Runner { + "_aliasCount": 0, + "_name": "disposeBuffer", + "items": Array [], + }, + "id": 1, + "index": true, + "static": false, + }, + "indices": Array [], + "indicesUint16": null, + "instanceCount": 1, + "instanced": false, + "points": Array [], + "refCount": 1, + "shapeIndex": 0, + "textureIds": Array [], + "uvs": Array [], + "uvsFloat32": null, + }, + "_holeMode": false, + "_lastSortedIndex": 0, + "_lineStyle": LineStyle { + "alignment": 0.5, + "alpha": 1, + "cap": "butt", + "color": 0, + "join": "miter", + "matrix": null, + "miterLimit": 10, + "native": false, + "texture": Texture { + "_events": Object {}, + "_eventsCount": 0, + "_frame": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "_rotate": 0, + "_updateID": 1, + "_uvs": TextureUvs { + "uvsFloat32": Float32Array [ + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + ], + "x0": 0, + "x1": 1, + "x2": 1, + "x3": 0, + "y0": 0, + "y1": 0, + "y2": 1, + "y3": 1, + }, + "baseTexture": BaseTexture { + "_batchEnabled": 0, + "_batchLocation": 0, + "_events": Object { + "update": EE { + "context": [Circular], + "fn": [Function], + "once": false, + }, + }, + "_eventsCount": 1, + "_glTextures": Object {}, + "alphaMode": 1, + "anisotropicLevel": 0, + "cacheId": null, + "destroy": [Function], + "destroyed": false, + "dirtyId": 0, + "dirtyStyleId": 0, + "emit": [Function], + "format": 6408, + "height": 16, + "isPowerOfTwo": true, + "mipmap": 1, + "on": [Function], + "once": [Function], + "parentTextureArray": null, + "resolution": 1, + "resource": CanvasResource { + "_height": 16, + "_width": 16, + "destroyed": false, + "internal": false, + "noSubImage": false, + "onError": Runner { + "_aliasCount": 0, + "_name": "onError", + "items": Array [ + [Circular], + ], + }, + "onResize": Runner { + "_aliasCount": 0, + "_name": "setRealSize", + "items": Array [ + [Circular], + ], + }, + "onUpdate": Runner { + "_aliasCount": 0, + "_name": "update", + "items": Array [ + [Circular], + ], + }, + "source": , + }, + "scaleMode": 1, + "target": 3553, + "textureCacheIds": Array [], + "touched": 0, + "type": 5121, + "uid": 2, + "valid": true, + "width": 16, + "wrapMode": 33071, + }, + "defaultAnchor": Point { + "x": 0, + "y": 0, + }, + "destroy": [Function], + "emit": [Function], + "noFrame": true, + "on": [Function], + "once": [Function], + "orig": Rectangle { + "height": 16, + "type": 1, + "width": 16, + "x": 0, + "y": 0, + }, + "textureCacheIds": Array [], + "trim": undefined, + "uvMatrix": null, + "valid": true, + }, + "visible": false, + "width": 0, + }, + "_localBounds": null, + "_localBoundsRect": null, + "_mask": null, + "_matrix": null, + "_tint": 16777215, + "_transformID": -1, + "_zIndex": 0, + "alpha": 1, + "batchDirty": -1, + "batchTint": -1, + "batches": Array [], + "children": Array [ + [Circular], + ], + "currentPath": null, + "filterArea": null, + "filters": null, + "isMask": false, + "isSprite": false, + "parent": null, + "pluginName": "batch", + "renderable": true, + "shader": null, + "sortDirty": true, + "sortableChildren": false, + "state": State { + "_blendMode": 0, + "_polygonOffset": 0, + "data": 1, + }, + "tempDisplayObjectParent": null, + "transform": Transform { + "_currentLocalID": 0, + "_cx": 1, + "_cy": 0, + "_localID": 0, + "_parentID": 0, + "_rotation": 0, + "_sx": 0, + "_sy": 1, + "_worldID": 0, + "localTransform": Matrix { + "a": 1, + "array": null, + "b": 0, + "c": 0, + "d": 1, + "tx": 0, + "ty": 0, + }, + "pivot": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "position": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "scale": ObservablePoint { + "_x": 1, + "_y": 1, + "cb": [Function], + "scope": [Circular], + }, + "skew": ObservablePoint { + "_x": 0, + "_y": 0, + "cb": [Function], + "scope": [Circular], + }, + "worldTransform": Matrix { + "a": 1, + "array": null, + "b": 0, + "c": 0, + "d": 1, + "tx": 0, + "ty": 0, + }, + }, + "vertexData": null, + "visible": true, + "worldAlpha": 1, + }, "pluginName": "batch", "renderable": true, "shader": null, @@ -1011,7 +2055,7 @@ TimeGraphArrowComponent { "_cx": 1, "_cy": 0, "_localID": 0, - "_parentID": 0, + "_parentID": -1, "_rotation": 0, "_sx": 0, "_sy": 1, diff --git a/timeline-chart/src/components/__tests__/time-graph-arrow.test.ts b/timeline-chart/src/components/__tests__/time-graph-arrow.test.ts index f6f00c90..775cfa25 100644 --- a/timeline-chart/src/components/__tests__/time-graph-arrow.test.ts +++ b/timeline-chart/src/components/__tests__/time-graph-arrow.test.ts @@ -10,11 +10,11 @@ describe('TimeGraphArrow', () => { destinationId: 1, range } - const element = { + const coords = { start: { x: 0, y: 1 }, end: { x: 2, y: 3 } } - const component = new TimeGraphArrowComponent('Test', arrow, element); + const component = new TimeGraphArrowComponent('Test', arrow, coords); it ('Renders', () => { expect(component).toBeTruthy(); diff --git a/timeline-chart/src/layer/time-graph-chart-arrows.ts b/timeline-chart/src/layer/time-graph-chart-arrows.ts index 2b239918..f929b91f 100644 --- a/timeline-chart/src/layer/time-graph-chart-arrows.ts +++ b/timeline-chart/src/layer/time-graph-chart-arrows.ts @@ -6,6 +6,7 @@ import { TimeGraphChartLayer } from "./time-graph-chart-layer"; export class TimeGraphChartArrows extends TimeGraphChartLayer { protected arrows: Map; + protected rowIds: number[] = []; private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; }; protected afterAddToContainer() { @@ -17,27 +18,36 @@ export class TimeGraphChartArrows extends TimeGraphChartLayer { }); } - protected getCoordinates(arrow: TimelineChart.TimeGraphArrow): TimeGraphArrowCoordinates { + protected getCoordinates(arrow: TimelineChart.TimeGraphArrow): TimeGraphArrowCoordinates | undefined { + const sourceIndex = this.rowIds.indexOf(arrow.sourceId); + const destinationIndex = this.rowIds.indexOf(arrow.destinationId); + if (sourceIndex === -1 || destinationIndex === -1) { + return undefined; + } const relativeStartPosition = arrow.range.start - this.unitController.viewRange.start; const start: TimeGraphElementPosition = { x: this.getPixel(relativeStartPosition), - y: (arrow.sourceId * this.rowController.rowHeight) + (this.rowController.rowHeight / 2) + y: (sourceIndex * this.rowController.rowHeight) + (this.rowController.rowHeight / 2) } const end: TimeGraphElementPosition = { x: this.getPixel(relativeStartPosition + arrow.range.end - arrow.range.start), - y: (arrow.destinationId * this.rowController.rowHeight) + (this.rowController.rowHeight / 2) + y: (destinationIndex * this.rowController.rowHeight) + (this.rowController.rowHeight / 2) } return { start, end }; } protected addArrow(arrow: TimelineChart.TimeGraphArrow) { const coords = this.getCoordinates(arrow); + if (!coords) { + return; + } const arrowComponent = new TimeGraphArrowComponent('arrow', arrow, coords); this.arrows.set(arrow, arrowComponent); this.addChild(arrowComponent); } - addArrows(arrows: TimelineChart.TimeGraphArrow[]): void { + addArrows(arrows: TimelineChart.TimeGraphArrow[], rowIds: number[]): void { + this.rowIds = rowIds; if (!this.stateController) { throw ('Add this TimeGraphChartArrows to a container before adding arrows.'); } @@ -59,10 +69,15 @@ export class TimeGraphChartArrows extends TimeGraphChartLayer { } protected updateArrow(arrow: TimelineChart.TimeGraphArrow) { - const { start, end } = this.getCoordinates(arrow); const arrowComponent = this.arrows.get(arrow); if (arrowComponent) { - arrowComponent.update({ start, end }); + const coords = this.getCoordinates(arrow); + if (!coords) { + this.removeChild(arrowComponent); + this.arrows.delete(arrow); + } else { + arrowComponent.update(coords); + } } }