|
@@ -1,7 +1,15 @@
|
|
|
import React from 'react';
|
|
|
import { createRoot } from 'react-dom/client';
|
|
|
+import { updateSiteColors } from '../tmdet-extension/tmdet-color-theme';
|
|
|
+import { RcsbFv, RcsbFvBoardConfigInterface } from '@rcsb/rcsb-saguaro';
|
|
|
+import { fetchDescriptor } from '../UniTmpHelper';
|
|
|
+import { setRegionColors } from '../FeatureViewConfig';
|
|
|
|
|
|
-export type TmFv1DParams = {
|
|
|
+const defaultViewerWidth = 600;
|
|
|
+const defaultRowTitleWidth = 100;
|
|
|
+const ULTIMATE_GAP_CONSTANT = 4; // I do not know why it is 4.
|
|
|
+
|
|
|
+type TmFv1DParams = {
|
|
|
elementId: string,
|
|
|
url: string,
|
|
|
side1: string,
|
|
@@ -9,7 +17,13 @@ export type TmFv1DParams = {
|
|
|
rowTitleWidth?: number
|
|
|
};
|
|
|
|
|
|
-export class TmFv1D extends React.Component {
|
|
|
+type TmFv1DState = {
|
|
|
+ featureViewer?: RcsbFv,
|
|
|
+ num?: number
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+export class TmFv1D extends React.Component<TmFv1DParams, TmFv1DState> {
|
|
|
|
|
|
protected containerRef = React.createRef<HTMLDivElement>();
|
|
|
|
|
@@ -17,20 +31,39 @@ export class TmFv1D extends React.Component {
|
|
|
super(props);
|
|
|
}
|
|
|
|
|
|
- public componentDidMount(): void {
|
|
|
+ public async componentDidMount(): Promise<void> {
|
|
|
+ console.log('PROPS', this.props);
|
|
|
+
|
|
|
+ await createRcsbFeatureViewer({
|
|
|
+ elementId: this.props.elementId,
|
|
|
+ url: this.props.url,
|
|
|
+ side1: this.props.side1,
|
|
|
+ rowTitleWidth: this.props.rowTitleWidth,
|
|
|
+ trackWidth: this.props.trackWidth
|
|
|
+ });
|
|
|
+
|
|
|
new ResizeObserver(this.resize)
|
|
|
.observe(this.containerRef.current as Element);
|
|
|
}
|
|
|
|
|
|
- resize() {
|
|
|
- console.log('Observer works');
|
|
|
+ resize(entries: ResizeObserverEntry[], observer: ResizeObserver) {
|
|
|
+ console.log('Observer params', [ entries, observer ]);
|
|
|
+ const currentId = entries[0].target.id;
|
|
|
+ const observerEntry = entries[0];
|
|
|
+ const featureViewer = featureViewerRegistry.get(currentId) as RcsbFv;
|
|
|
+ const boardConfig = featureViewer.getBoardConfig();
|
|
|
+ boardConfig.trackWidth = observerEntry.contentRect.width - boardConfig.rowTitleWidth!;
|
|
|
+ scaleBoardConfigWidths(currentId, boardConfig, observerEntry);
|
|
|
+
|
|
|
+ featureViewer.updateBoardConfig({ boardConfigData: boardConfig });
|
|
|
}
|
|
|
|
|
|
public render(): JSX.Element {
|
|
|
return (
|
|
|
- <div ref={this.containerRef} style={{ borderWidth: "1px", borderStyle: "solid", borderBlockColor: "black" }}>
|
|
|
- Hello
|
|
|
- </div>
|
|
|
+ <div ref={this.containerRef}
|
|
|
+ id={ this.props.elementId }
|
|
|
+ style={{ borderWidth: "0px", padding: "0px" }}
|
|
|
+ />
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -38,11 +71,84 @@ export class TmFv1D extends React.Component {
|
|
|
|
|
|
export class TmFv1DElement extends HTMLElement {
|
|
|
|
|
|
- constructor() {
|
|
|
- super();
|
|
|
+ connectedCallback() {
|
|
|
const root = createRoot(this);
|
|
|
+
|
|
|
+ const elementId = this.getAttribute("elementId")!;
|
|
|
+ const url = this.getAttribute("url")!;
|
|
|
+ const side1 = this.getAttribute("side1")!;
|
|
|
+ const calculatedWidth = calculateViewerWidth(this.parentElement);
|
|
|
+ const rowTitleWidth = parseInt(this.getAttribute("rowTitleWidth")!)
|
|
|
+ || defaultRowTitleWidth;
|
|
|
+ const trackWidth = (parseInt(this.getAttribute("trackWidth")!)
|
|
|
+ || calculatedWidth) - rowTitleWidth;
|
|
|
+ console.log('Widths:', [ rowTitleWidth, trackWidth ]);
|
|
|
+
|
|
|
root.render(
|
|
|
- <TmFv1D></TmFv1D>
|
|
|
+ <TmFv1D
|
|
|
+ elementId={ elementId }
|
|
|
+ url={ url }
|
|
|
+ side1={ side1 }
|
|
|
+ trackWidth={ trackWidth }
|
|
|
+ rowTitleWidth={ rowTitleWidth }
|
|
|
+ />
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+function calculateViewerWidth(parent: HTMLElement|null) {
|
|
|
+ if (!parent) {
|
|
|
+ return defaultViewerWidth;
|
|
|
+ }
|
|
|
+ const boundingRect = parent.getBoundingClientRect();
|
|
|
+ const computedStyle = window.getComputedStyle(parent);
|
|
|
+ const extraWidth = parseInt(computedStyle.paddingLeft)
|
|
|
+ + parseInt(computedStyle.paddingRight)
|
|
|
+ + parseInt(computedStyle.borderLeftWidth)
|
|
|
+ + parseInt(computedStyle.borderRightWidth);
|
|
|
+
|
|
|
+ return boundingRect.width - extraWidth - ULTIMATE_GAP_CONSTANT;
|
|
|
+}
|
|
|
+
|
|
|
+const featureViewerRegistry = new Map();
|
|
|
+
|
|
|
+/**
|
|
|
+ * Create an Rcsb Saguaro 1D viewer instance.
|
|
|
+ *
|
|
|
+ * @param elementId id of parent element
|
|
|
+ * @param url source of JSON config
|
|
|
+ * @param side1 side1 paramter to update site colors, if it is needed
|
|
|
+ */
|
|
|
+export async function createRcsbFeatureViewer(params: {
|
|
|
+ elementId: string, url: string, side1: string, trackWidth?: number, rowTitleWidth?: number }): Promise<RcsbFv> {
|
|
|
+
|
|
|
+ updateSiteColors(params.side1 as any);
|
|
|
+
|
|
|
+ const featureTracks = await fetchDescriptor(params.url);
|
|
|
+ const blockConfig = featureTracks.blockConfig;
|
|
|
+ const boardConfig = blockConfig[0].featureViewConfig[0].boardConfig;
|
|
|
+ boardConfig.trackWidth = params.trackWidth ?? 600;
|
|
|
+ boardConfig.rowTitleWidth = params.rowTitleWidth ?? 160;
|
|
|
+
|
|
|
+ const rowConfig = blockConfig[0].featureViewConfig[0].rowConfig;
|
|
|
+ setRegionColors(rowConfig);
|
|
|
+
|
|
|
+ const pfv = new RcsbFv({
|
|
|
+ boardConfigData: boardConfig,
|
|
|
+ rowConfigData: rowConfig,
|
|
|
+ elementId: params.elementId
|
|
|
+ });
|
|
|
+ featureViewerRegistry.set(params.elementId, pfv);
|
|
|
+
|
|
|
+ return pfv;
|
|
|
+}
|
|
|
+
|
|
|
+function scaleBoardConfigWidths(elementId: string, boardConfig: RcsbFvBoardConfigInterface, entry: ResizeObserverEntry) {
|
|
|
+ const container = document.getElementById(elementId);
|
|
|
+ const fullWidth = boardConfig.trackWidth! + boardConfig.rowTitleWidth! + ULTIMATE_GAP_CONSTANT;
|
|
|
+ const ratio = entry.contentRect.width / fullWidth;
|
|
|
+ console.log('Before scaling', [ boardConfig.trackWidth, boardConfig.rowTitleWidth, ratio ]);
|
|
|
+ boardConfig.trackWidth = Math.floor(ratio * boardConfig.trackWidth!);
|
|
|
+ boardConfig.rowTitleWidth! = Math.floor(ratio * boardConfig.rowTitleWidth!);
|
|
|
+ console.log('After scaling', [ boardConfig.trackWidth, boardConfig.rowTitleWidth ]);
|
|
|
+}
|