Skip to content

Commit

Permalink
fix(core): preserve zoom status when new track added (#971)
Browse files Browse the repository at this point in the history
* fix: preserve zoom status when new track added

* chore: format
  • Loading branch information
sehilyi authored Sep 22, 2023
1 parent 09a5207 commit 875a9b5
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 8 deletions.
8 changes: 7 additions & 1 deletion editor/example/json-spec/responsive-track-wise-comparison.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { DomainChrInterval, GoslingSpec, OverlaidTracks, SingleTrack, TemplateTrack } from '@gosling-lang/gosling-schema';
import type {
DomainChrInterval,
GoslingSpec,
OverlaidTracks,
SingleTrack,
TemplateTrack
} from '@gosling-lang/gosling-schema';
import { GOSLING_PUBLIC_DATA } from './gosling-data';

const trackColor = {
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/spec-preprocess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function traverseViewArrangements(spec: GoslingSpec, callback: (tv: Multi
export function convertToFlatTracks(spec: SingleView): Track[] {
if (IsFlatTracks(spec)) {
// This is already `FlatTracks`, so just override the view definition
const base = {...spec, tracks: undefined, id: undefined };
const base = { ...spec, tracks: undefined, id: undefined };
return spec.tracks
.filter(track => !track._invalidTrack)
.map(track => Object.assign(JSON.parse(JSON.stringify(base)), track) as SingleTrack);
Expand All @@ -117,7 +117,7 @@ export function convertToFlatTracks(spec: SingleView): Track[] {
} as Track);
} else {
// Override track definitions from views
const base = {...spec, tracks: undefined, id: undefined };
const base = { ...spec, tracks: undefined, id: undefined };
const newSpec = Object.assign(JSON.parse(JSON.stringify(base)), track) as SingleTrack;
newTracks.push(newSpec);
}
Expand Down
28 changes: 28 additions & 0 deletions src/core/gosling-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ 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 Expand Up @@ -115,6 +137,10 @@ export const GoslingComponent = forwardRef<GoslingRef, GoslingCompProps>((props,
if (props.experimental?.reactive && isMountedOnce) {
// Use API to update visualization.
setTimeout(() => {
preverseZoomStatus(
newHiGlassSpec,
hgRef.current?.api.getViewConfig() as gosling.HiGlassSpec
);
hgRef.current?.api.setViewConfig(newHiGlassSpec);
}, DELAY_FOR_CONTAINER_RESIZE_BEFORE_RERENDER);
} else {
Expand All @@ -138,6 +164,8 @@ export const GoslingComponent = forwardRef<GoslingRef, GoslingCompProps>((props,

// TODO: If not necessary, do not update `wrapperSize` (i.e., when responsiveSize is not set)
useEffect(() => {
if (!props.spec?.responsiveSize) return;

const containerElement = document.getElementById(wrapperDivId);
if (!containerElement) return;

Expand Down
11 changes: 9 additions & 2 deletions src/core/utils/overlay.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { AxisPosition, SingleTrack, OverlaidTrack, Track, ChannelDeep, DataDeep } from '@gosling-lang/gosling-schema';
import type {
AxisPosition,
SingleTrack,
OverlaidTrack,
Track,
ChannelDeep,
DataDeep
} from '@gosling-lang/gosling-schema';
import { IsChannelDeep, IsDataTrack, IsOverlaidTrack, IsSingleTrack, IsDummyTrack } from '@gosling-lang/gosling-schema';

/**
Expand Down Expand Up @@ -77,7 +84,7 @@ export function spreadTracksByData(tracks: Track[]): Track[] {
return [t];
}

const base: Partial<OverlaidTrack> = {...t, id: undefined, overlay: undefined };
const base: Partial<OverlaidTrack> = { ...t, id: undefined, overlay: undefined };
const spread: Track[] = [];
const original: OverlaidTrack = JSON.parse(JSON.stringify(base));
original.overlay = [];
Expand Down
2 changes: 1 addition & 1 deletion src/gosling-schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export * from './gosling.schema';
export * from './gosling.schema.guards';
export * from './validate';
export { default as ThemeSchema } from './theme.schema.json';
export { default as GoslingSchema } from './gosling.schema.json';
export { default as GoslingSchema } from './gosling.schema.json';
2 changes: 1 addition & 1 deletion src/higlass-schema/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './higlass.schema';
export { default as HiGlassSchema } from './higlass.schema.json';
export { default as HiGlassSchema } from './higlass.schema.json';
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export { compile } from './compiler/compile';
export { validateGoslingSpec } from '@gosling-lang/gosling-schema';
export { GoslingComponent } from './core/gosling-component';
export type { GoslingRef } from './core/gosling-component';
export { embed } from './core/gosling-embed';
export { embed } from './core/gosling-embed';

0 comments on commit 875a9b5

Please sign in to comment.