Skip to content

Commit

Permalink
Fetch visible rows only
Browse files Browse the repository at this point in the history
Add row provider interface to fetch the full list of row ids.

Add selected row index to TimeGraphRowController to allow for the case
where the selected row model is not yet available. Allow for selected
row model to be undefined.

When the list of row ids changes, delete row component for removed rows
and update the y-position of existing rows. Update the selected row
index. Create placeholder rows for new rows until their row model is
fetched.

Allow for placeholder rows to be created and displayed while the row
model is being fetched, by allowing constructor with undefined row
model.

Make each TimeGraphRowComponent have its own providedModel (range and
resolution) object so that each row can determine independently if it
needs to fetch new data when the view range or resolution changes.

Compute the list of visible row ids (with a few extra buffered rows) and
filter out those that already have the correct model. Fetch the row
model of only the necessary rows.

When the row models are received, destroy only the row components to be
updated and recreate them. The other row components are left untouched.

Move states and annotations from the TimeGraphChartLayer to be children
of their respective TimeGraphRowComponent instead.

If a newly created row component is at the selected row index, select
it.

In updateScaleAndPosition(), iterate through existing row components
instead of row models. Handle placeholder rows that have no states or
annotations.

Allow row style provider to provide default style for placeholder rows
when row model is undefined.

Call the debounced maybeFetchNewData() method when the vertical offset
is changed to fetch row model of rows that become visible.

Remove getRowModels() method as all row models are not always available.
Add getRowModel(index) method.

Replace getElementById() with getStateById(). Iterate through the row
components to find the state.

Move arrow up/down navigation from TimeGraphChartCursors layer to
TimeGraphChart layer. Ensure the newly selected row is visible.

Make options optional in update of annotation.

Clear the row components map at destroy() and removeChildren().

Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
  • Loading branch information
PatrickTasse committed May 10, 2022
1 parent 100418b commit 90696d3
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 189 deletions.
5 changes: 5 additions & 0 deletions example/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ unitController.numberTranslator = (theNumber: bigint) => {
};

const providers = {
rowProvider: () => {
return {
rowIds : testDataProvider.getRowIds()
};
},
dataProvider: (range: TimelineChart.TimeGraphRange, resolution: number) => {
const length = range.end - range.start;
const overlap = length * BigInt(10);
Expand Down
2 changes: 1 addition & 1 deletion timeline-chart/src/components/time-graph-annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class TimeGraphAnnotationComponent extends TimeGraphComponent<TimelineCha
this.update(_options);
}

update(opts: TimeGraphAnnotationComponentOptions): void {
update(opts?: TimeGraphAnnotationComponentOptions): void {
if (opts) {
this._options.position.x = opts.position.x;
this.updateYPosition();
Expand Down
55 changes: 49 additions & 6 deletions timeline-chart/src/components/time-graph-row.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TimeGraphComponent, TimeGraphElementPosition, TimeGraphParentComponent, TimeGraphStyledRect } from "./time-graph-component";
import { TimelineChart } from "../time-graph-model";
import { TimeGraphStateComponent } from "./time-graph-state";
import { TimeGraphAnnotationComponent } from "./time-graph-annotation";

export interface TimeGraphRowStyle {
backgroundColor?: number
Expand All @@ -12,13 +13,15 @@ export interface TimeGraphRowStyle {

export class TimeGraphRow extends TimeGraphComponent<TimelineChart.TimeGraphRowModel> implements TimeGraphParentComponent {

protected states: TimeGraphStateComponent[] = [];
protected _providedModel: { range: TimelineChart.TimeGraphRange, resolution: number };
protected _rowStateComponents: Map<string, TimeGraphStateComponent> = new Map();
protected _rowAnnotationComponents: Map<string, TimeGraphAnnotationComponent> = new Map();

constructor(
id: string,
protected _options: TimeGraphStyledRect,
protected _rowIndex: number,
model: TimelineChart.TimeGraphRowModel,
model?: TimelineChart.TimeGraphRowModel,
protected _style: TimeGraphRowStyle = { lineOpacity: 0.5, lineThickness: 1, backgroundOpacity: 0 }) {
super(id, undefined, model);
}
Expand Down Expand Up @@ -55,10 +58,42 @@ export class TimeGraphRow extends TimeGraphComponent<TimelineChart.TimeGraphRowM
return this._options.height;
}

// Gets called by TimeGraphLayer. Don't call it unless you know what you are doing.
addChild(state: TimeGraphStateComponent) {
this.states.push(state);
this._displayObject.addChild(state.displayObject);
addChild(child: TimeGraphComponent<any>): void {
this._displayObject.addChild(child.displayObject);
child.update();
}

removeChild(child: TimeGraphComponent<any>): void {
this._displayObject.removeChild(child.displayObject);
child.destroy();
}

addState(stateComponent: TimeGraphStateComponent) {
this._rowStateComponents.set(stateComponent.id, stateComponent);
this.addChild(stateComponent);
}

removeState(stateComponent: TimeGraphStateComponent) {
this._rowStateComponents.delete(stateComponent.id);
this.removeChild(stateComponent);
}

getStateById(id: string) {
return this._rowStateComponents.get(id);
}

addAnnotation(annotationComponent: TimeGraphAnnotationComponent) {
this._rowAnnotationComponents.set(annotationComponent.id, annotationComponent);
this.addChild(annotationComponent);
}

removeAnnotation(annotationComponent: TimeGraphAnnotationComponent) {
this._rowAnnotationComponents.delete(annotationComponent.id);
this.removeChild(annotationComponent);
}

getAnnotationById(id: string) {
return this._rowAnnotationComponents.get(id);
}

get style() {
Expand All @@ -83,4 +118,12 @@ export class TimeGraphRow extends TimeGraphComponent<TimelineChart.TimeGraphRowM
}
this.update();
}

get providedModel() {
return this._providedModel;
}

set providedModel(providedModel: { range: TimelineChart.TimeGraphRange, resolution: number }) {
this._providedModel = providedModel;
}
}
38 changes: 0 additions & 38 deletions timeline-chart/src/layer/time-graph-chart-cursors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
this.navigateOrSelectLeft();
} else if (event.keyCode === keyboardKey.ArrowRight) {
this.navigateOrSelectRight();
} else if (event.keyCode === keyboardKey.ArrowUp) {
this.navigateUp();
} else if (event.keyCode === keyboardKey.ArrowDown) {
this.navigateDown();
}
};

Expand Down Expand Up @@ -200,40 +196,6 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
}
}

protected navigateDown() {
const rows = this.chartLayer.getRowModels();
let selectedRow = this.rowController.selectedRow;
const idx = rows.findIndex(row => row === selectedRow);
if (idx < rows.length) {
this.chartLayer.selectRow(rows[idx + 1]);
}
selectedRow = this.rowController.selectedRow;
const state = selectedRow.states.find(state => {
if (this.unitController.selectionRange) {
return state.range.start <= this.unitController.selectionRange.start && state.range.end > this.unitController.selectionRange.start;
}
return false;
});
state && this.chartLayer.selectState(state);
}

protected navigateUp() {
const rows = this.chartLayer.getRowModels();
let selectedRow = this.rowController.selectedRow;
const idx = rows.findIndex(row => row === selectedRow);
if (idx > 0) {
this.chartLayer.selectRow(rows[idx - 1]);
}
selectedRow = this.rowController.selectedRow;
const state = selectedRow.states.find(state => {
if (this.unitController.selectionRange) {
return state.range.start <= this.unitController.selectionRange.start && state.range.end > this.unitController.selectionRange.start;
}
return false;
})
state && this.chartLayer.selectState(state);
}

centerCursor() {
if (this.unitController.selectionRange) {
const cursorPosition = this.unitController.selectionRange.end;
Expand Down
Loading

0 comments on commit 90696d3

Please sign in to comment.