Skip to content

Commit

Permalink
fix(core): preserve the zoom status only when needed (#974)
Browse files Browse the repository at this point in the history
* fix: preserve the zoom status only when needed

* chore: format

* chore: move import

* chore: remove imports

* chore: remove unused
  • Loading branch information
sehilyi committed Sep 27, 2023
1 parent 6ddb4b6 commit b74f10e
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 23 deletions.
1 change: 0 additions & 1 deletion src/compiler/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export type CompileCallback = (
idTable: IdTable
) => void;


export function compile(
spec: GoslingSpec,
callback: CompileCallback,
Expand Down
23 changes: 1 addition & 22 deletions src/core/gosling-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { isEqual } from 'lodash-es';
import * as uuid from 'uuid';
import { publish } from '../api/pubsub';
import type { IdTable } from '../api/track-and-view-ids';
import { preverseZoomStatus } from './utils/higlass-zoom-config';

// Before rerendering, wait for a few time so that HiGlass container is resized already.
// If HiGlass is rendered and then the container resizes, the viewport position changes, unmatching `xDomain` specified by users.
Expand Down Expand Up @@ -88,28 +89,6 @@ export const GoslingComponent = forwardRef<GoslingRef, GoslingCompProps>((props,
[viewConfig, theme]
);

/**
* This makes sure that all the current zooming status is preserved when new tracks are added
*/
const preverseZoomStatus = (newSpec: gosling.HiGlassSpec, prevSpec: gosling.HiGlassSpec) => {
newSpec.views.forEach(view => {
const viewUid = view.uid!;
const newView = !prevSpec.views.find(v => v.uid === viewUid);
if (newView) {
// if this view is linked with another view, we need to preverse the current zooming status of this view from the linked view
// Otherwise, all the views that is linked with this view will be reset to the original zooming position
const { locksByViewUid } = newSpec.zoomLocks;
const lockUid = locksByViewUid[viewUid];
const linkedViewUid = Object.entries(locksByViewUid).find(([_, uid]) => _ && uid === lockUid)?.[0];
if (linkedViewUid) {
// We found a linked view, so copy the current zooming status
view.initialXDomain = prevSpec.views.find(v => v.uid === linkedViewUid)?.initialXDomain;
view.initialYDomain = prevSpec.views.find(v => v.uid === linkedViewUid)?.initialYDomain;
}
}
});
};

// TODO: add a `force` parameter since changing `linkingId` might not update vis
const compile = useCallback(() => {
if (props.spec) {
Expand Down
64 changes: 64 additions & 0 deletions src/core/utils/higlass-zoom-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { HiGlassSpec, View } from '@gosling-lang/higlass-schema';
import { preverseZoomStatus } from './higlass-zoom-config';

describe('Management of HiGlass view configs', () => {
const viewBase: Pick<View, 'tracks' | 'layout'> = {
tracks: {
top: [],
left: [],
center: [],
right: [],
bottom: [],
gallery: [],
whole: []
},
layout: {
x: 0,
y: 0,
w: 0,
h: 0
}
};
const prev: HiGlassSpec = {
views: [{ ...viewBase, uid: 'existing-view', initialXDomain: [0, 1], initialYDomain: [0, 1] }],
zoomLocks: { locksByViewUid: {}, locksDict: {} },
locationLocks: { locksByViewUid: {}, locksDict: {} }
};
it('Should preserve zoom status', () => {
const cur: HiGlassSpec = {
views: [
{ ...viewBase, uid: 'existing-view', initialXDomain: [0, 1], initialYDomain: [0, 1] },
{ ...viewBase, uid: 'new-view', initialXDomain: [0, 999], initialYDomain: [0, 999] }
],
zoomLocks: {
locksByViewUid: {
'existing-view': 'lock-id',
'new-view': 'lock-id'
},
locksDict: {}
},
locationLocks: { locksByViewUid: {}, locksDict: {} }
};
preverseZoomStatus(cur, prev);
expect(cur.views[0].initialXDomain).toEqual(cur.views[1].initialXDomain);
});
it("Shouldn't preserve zoom status", () => {
// This example is a new visualization, not containing any previous view.
const cur: HiGlassSpec = {
views: [
{ ...viewBase, uid: 'new-view-1', initialXDomain: [0, 1], initialYDomain: [0, 1] },
{ ...viewBase, uid: 'new-view-2', initialXDomain: [0, 999], initialYDomain: [0, 999] }
],
zoomLocks: {
locksByViewUid: {
'new-view-1': 'lock-id',
'new-view-2': 'lock-id'
},
locksDict: {}
},
locationLocks: { locksByViewUid: {}, locksDict: {} }
};
preverseZoomStatus(cur, prev);
expect(cur.views[0].initialXDomain).not.toEqual(cur.views[1].initialXDomain);
});
});
25 changes: 25 additions & 0 deletions src/core/utils/higlass-zoom-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { HiGlassSpec } from '@gosling-lang/higlass-schema';

/**
* This makes sure that all the current zooming status is preserved when new tracks are added
*/
export const preverseZoomStatus = (newSpec: HiGlassSpec, prevSpec: HiGlassSpec) => {
newSpec.views.forEach(view => {
const viewUid = view.uid!;
const isNewView = !prevSpec.views.find(v => v.uid === viewUid);
if (isNewView) {
// if this view is linked with another view, we need to preverse the current zooming status of this view from the linked view
// Otherwise, all the views that is linked with this view will be reset to the original zooming position
const { locksByViewUid } = newSpec.zoomLocks;
const lockUid = locksByViewUid[viewUid];
const linkedViewUid = Object.entries(locksByViewUid).find(([_, uid]) => _ && uid === lockUid)?.[0];
// Only if the linked view existed in the previous spec, we copy the zooming status
const linkedViewExistedPrev = !!prevSpec.views.find(v => v.uid === linkedViewUid);
if (linkedViewUid && linkedViewExistedPrev) {
// We found a linked view, so copy the current zooming status
view.initialXDomain = prevSpec.views.find(v => v.uid === linkedViewUid)?.initialXDomain;
view.initialYDomain = prevSpec.views.find(v => v.uid === linkedViewUid)?.initialYDomain;
}
}
});
};

0 comments on commit b74f10e

Please sign in to comment.