171 lines
5.7 KiB
JavaScript
171 lines
5.7 KiB
JavaScript
import { Session } from 'meteor/session';
|
|
import { Tracker } from 'meteor/tracker';
|
|
|
|
import { OHIF } from 'meteor/ohif:core';
|
|
|
|
import { OHIFPlugin } from "./OHIFPlugin";
|
|
|
|
export class ViewportPlugin extends OHIFPlugin {
|
|
constructor(name) {
|
|
super();
|
|
|
|
this.name = name;
|
|
this._destroyed = false;
|
|
|
|
this._setupListeners();
|
|
}
|
|
|
|
/**
|
|
* Retrieve a Display Set for a specific viewport by viewport index,
|
|
* if one is already displayed in the viewport.
|
|
*
|
|
* @static
|
|
* @param {Number} viewportIndex
|
|
* @return {undefined|ImageSet}
|
|
*/
|
|
static getDisplaySet(viewportIndex) {
|
|
// TODO: Move layoutManager from viewerbase to viewer
|
|
const { layoutManager } = OHIF.viewerbase;
|
|
const viewportData = layoutManager.viewportData[viewportIndex];
|
|
const { studyInstanceUid, displaySetInstanceUid } = viewportData;
|
|
const studyMetadata = OHIF.viewer.StudyMetadataList.findBy({ studyInstanceUID: studyInstanceUid });
|
|
|
|
return studyMetadata.findDisplaySet(displaySet => {
|
|
return displaySet.displaySetInstanceUid === displaySetInstanceUid;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Set up the viewport using the plugin.
|
|
*
|
|
* This should be implemented by the child class.
|
|
*
|
|
* @abstract
|
|
*
|
|
* @param {HTMLElement} div
|
|
* @param {ImageSet} displaySet
|
|
* @param {Object} viewportDetails
|
|
*/
|
|
setupViewport(div, displaySet, viewportDetails) {
|
|
throw new Error('You must override this method!');
|
|
}
|
|
|
|
/**
|
|
* Switch a single viewport to use the current ViewportPlugin
|
|
*
|
|
* @param {Number} viewportIndex The viewport to switch to the current plugin type
|
|
*/
|
|
setViewportToPlugin(viewportIndex) {
|
|
if (!this.name) {
|
|
throw new Error('ViewportPlugin subclasses must have a name');
|
|
}
|
|
|
|
const { layoutManager } = OHIF.viewerbase;
|
|
const viewportData = layoutManager.viewportData[viewportIndex];
|
|
if (viewportData.plugin === this.name) {
|
|
OHIF.log.info(`setViewportToPlugin: Viewport ${viewportIndex} already set to plugin ${this.name}`);
|
|
}
|
|
|
|
viewportData.plugin = this.name;
|
|
|
|
layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, viewportData);
|
|
}
|
|
|
|
/**
|
|
* Runs 'setupViewport' for the ViewportPlugin on all viewports which should
|
|
* be rendered by this plugin, but have not yet been initialized. Viewports
|
|
* which already contain contents are skipped.
|
|
*
|
|
* @private
|
|
*/
|
|
_initEmptyPluginViewports() {
|
|
if (!this.name) {
|
|
throw new Error('ViewportPlugin subclasses must have a name');
|
|
}
|
|
|
|
// Find all Viewport HTMLElements currently using this plugin
|
|
const pluginDivs = Array.from(document.querySelectorAll(`.viewport-plugin-${this.name}`));
|
|
|
|
// If there are no Viewports using this plugin, stop here
|
|
if (!pluginDivs.length) {
|
|
return;
|
|
}
|
|
|
|
const emptyPluginDivs = pluginDivs.filter(div => {
|
|
// Keep only divs owned by the plugin which have no contents
|
|
return div.innerHTML.trim() === '';
|
|
});
|
|
|
|
OHIF.log.info(`${this.name}: Initializing ${emptyPluginDivs.length} viewports`);
|
|
|
|
// Retrieve the list of all viewports, so we can figure out the viewport details
|
|
const allViewports = Array.from(document.querySelectorAll('.viewportContainer'));
|
|
|
|
const { layoutManager } = OHIF.viewerbase;
|
|
|
|
emptyPluginDivs.forEach(div => {
|
|
// Identify the Viewport index, and any display set that is currently
|
|
// hung in the viewport
|
|
const viewportIndex = allViewports.indexOf(div.parentNode);
|
|
const viewportData = layoutManager.viewportData[viewportIndex];
|
|
const displaySet = ViewportPlugin.getDisplaySet(viewportIndex);
|
|
|
|
// Use the plugin's setupViewport function to render the contents
|
|
// of this viewport.
|
|
this.setupViewport(div, viewportData, displaySet);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Listen for changes to the viewport layout which would necessitate a
|
|
* rerendering of the viewports. When this happens, re-render all viewports
|
|
* which are using this plugin.
|
|
*
|
|
* @private
|
|
*/
|
|
_setupListeners() {
|
|
if (!this.name) {
|
|
throw new Error('ViewportPlugin subclasses must have a name');
|
|
}
|
|
|
|
console.warn(`_setupListeners: ${this.name}`);
|
|
|
|
// TODO: Stop using Meteor's reactivity here
|
|
Tracker.autorun((computation) => {
|
|
const random = Session.get('LayoutManagerUpdated');
|
|
console.warn(`LayoutManagerUpdated: ${this.name}: ${random}`);
|
|
|
|
// Bail out if this is the first time the autorun
|
|
// executes (i.e. when it is being defined).
|
|
//
|
|
// Note: This has to be checked after the dependency on the
|
|
// Session variable above, or the reactive dependency will not
|
|
// be established.
|
|
if (computation.firstRun === true) {
|
|
return;
|
|
}
|
|
|
|
// In case we need to disable the use
|
|
// of this plugin, we can also stop the
|
|
// reactive computation by setting
|
|
// this.destroyed to true.
|
|
if (this._destroyed === true) {
|
|
computation.stop();
|
|
}
|
|
|
|
// Identify all viewports which should be
|
|
// rendered by the ViewportPlugin, and render
|
|
// them.
|
|
this._initEmptyPluginViewports();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Stop listening for changes to the viewport layout in order to
|
|
* automatically rerender viewports setup for use by this plugin.
|
|
*/
|
|
stopListeners() {
|
|
this._destroyed = true;
|
|
}
|
|
}
|