diff --git a/LesionTracker/client/components/toolbarSection/toolbarSection.js b/LesionTracker/client/components/toolbarSection/toolbarSection.js
index d4f049c3f..b9abdc9c6 100644
--- a/LesionTracker/client/components/toolbarSection/toolbarSection.js
+++ b/LesionTracker/client/components/toolbarSection/toolbarSection.js
@@ -78,15 +78,6 @@ Template.toolbarSection.helpers({
disabled: isToolDisabled
});
- // Disabling this on Lesion Tracker
- // targetSubTools.push({
- // id: 'targetEX',
- // title: 'EX Target',
- // classes: 'imageViewerTool',
- // svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-measure-target-ex',
- // disabled: isToolDisabled
- // });
-
const extraTools = [];
extraTools.push({
@@ -145,14 +136,6 @@ Template.toolbarSection.helpers({
svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-elliptical-roi'
});
- extraTools.push({
- id: 'linkStackScroll',
- title: 'Link Scroll',
- classes: 'imageViewerCommand nonAutoDisableState',
- svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-link-stack-scroll',
- disableFunction: isStackScrollLinkingDisabled
- });
-
extraTools.push({
id: 'toggleCineDialog',
title: 'CINE',
@@ -184,15 +167,13 @@ Template.toolbarSection.helpers({
svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-pan'
});
- /*
- TODO: design the link functionality
- Commenting this out until we build this tool
buttonData.push({
id: 'link',
title: 'Link',
- classes: 'imageViewerCommand',
- svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-link'
- });*/
+ classes: 'imageViewerCommand toolbarSectionButton nonAutoDisableState',
+ svgLink: '/packages/ohif_viewerbase/assets/icons.svg#icon-tools-link',
+ disableFunction: isStackScrollLinkingDisabled
+ });
buttonData.push({
id: 'toggleTarget',
diff --git a/LesionTracker/client/components/viewer/viewer.js b/LesionTracker/client/components/viewer/viewer.js
index 1d7158353..dc3858fc0 100644
--- a/LesionTracker/client/components/viewer/viewer.js
+++ b/LesionTracker/client/components/viewer/viewer.js
@@ -40,7 +40,7 @@ Template.viewer.onCreated(() => {
flipH,
rotateL,
rotateR,
- linkStackScroll
+ link
});
if (ViewerData[contentId].loadedSeriesData) {
diff --git a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html
index 0d772c81d..5e0d582c9 100644
--- a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html
+++ b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html
@@ -9,6 +9,13 @@
{{studyDescription}}
{{formatDA studyDate}} {{formatTM studyTime}}
+ {{#if linked}}
+
+
+
+ {{/if}}
{{#if zoom}}Zoom: {{formatNumberPrecision zoom 0}}%{{/if}}
diff --git a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js
index 3ae7a9a4f..aad9ba92a 100644
--- a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js
+++ b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js
@@ -25,5 +25,10 @@ Template[defaultTemplate].helpers({
const timepoint = timepoints[0];
return timepointApi.name(timepoint);
+ },
+
+ linked: function() {
+ const linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports') || [];
+ return (linkedViewports.indexOf(this.viewportIndex) !== -1);
}
});
\ No newline at end of file
diff --git a/Packages/ohif-viewerbase/assets/icons.svg b/Packages/ohif-viewerbase/assets/icons.svg
index 59a205cdc..2b513ea4c 100644
--- a/Packages/ohif-viewerbase/assets/icons.svg
+++ b/Packages/ohif-viewerbase/assets/icons.svg
@@ -262,11 +262,11 @@
-
+
- Stack Scroll Sync
+ Viewport Link
-
+
diff --git a/Packages/ohif-viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js b/Packages/ohif-viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js
index a565356f3..c9f70e912 100644
--- a/Packages/ohif-viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js
+++ b/Packages/ohif-viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js
@@ -13,9 +13,11 @@ Template.toolbarSectionButton.onCreated(() => {
const currentId = instance.data.id;
const isCurrentTool = currentId === activeToolId;
const isSubTool = subTools && _.findWhere(subTools, { id: activeToolId });
+ const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || [];
+ const isActiveCommandButton = activeCommandButtons.indexOf(instance.data.id) !== -1;
- // Check if the current tool or a sub tool is the active one
- return isCurrentTool || isSubTool;
+ // Check if the current tool, a sub tool or a command button is active
+ return isCurrentTool || isSubTool || isActiveCommandButton;
};
instance.getActiveToolSubProperty = (propertyName, activeToolId) => {
diff --git a/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.styl b/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.styl
index 2ffa3e29e..f967130c6 100644
--- a/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.styl
+++ b/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.styl
@@ -39,3 +39,12 @@ $viewportTagPadding = 20px
&.controlsVisible
.topright, .bottomright
right: "calc(%s + 19px)" % $viewportTagPadding
+
+ svg
+ theme('color', '$defaultColor')
+ theme('fill', '$defaultColor')
+ theme('stroke', '$defaultColor')
+ background-color: transparent
+ margin: 2px
+ width: 18px
+ height: 18px
diff --git a/Packages/ohif-viewerbase/client/lib/stackImagePositionOffsetSynchronizer.js b/Packages/ohif-viewerbase/client/lib/stackImagePositionOffsetSynchronizer.js
index 6e046d19a..83959e46d 100644
--- a/Packages/ohif-viewerbase/client/lib/stackImagePositionOffsetSynchronizer.js
+++ b/Packages/ohif-viewerbase/client/lib/stackImagePositionOffsetSynchronizer.js
@@ -5,7 +5,7 @@ import { $ } from 'meteor/jquery';
class StackImagePositionOffsetSynchronizer {
constructor() {
this.active = false;
- this.syncedViewportElements = [];
+ this.syncedViewports = [];
this.synchronizer = new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.stackImagePositionOffsetSynchronizer)
}
@@ -22,16 +22,24 @@ class StackImagePositionOffsetSynchronizer {
return;
}
- const viewportElements = this.getLinkableViewports();
+ const viewports = this.getLinkableViewports();
+ const viewportIndexes = [];
- viewportElements.forEach((viewportElement, index) => {
- this.synchronizer.add(viewportElement);
- this.syncedViewportElements.push(viewportElement);
+ if(viewports.length <= 1) {
+ return;
+ }
+
+ viewports.forEach((viewport, index) => {
+ this.synchronizer.add(viewport.element);
+ this.syncedViewports.push(viewport);
+ viewportIndexes.push(viewport.index)
- $(viewportElement).on(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT, this.elementDisabledHandler(this));
+ $(viewport.element).on(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT, this.elementDisabledHandler(this));
});
this.active = true;
+ toolManager.activateCommandButton('link');
+ Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', viewportIndexes);
}
deactivate() {
@@ -39,12 +47,13 @@ class StackImagePositionOffsetSynchronizer {
return;
}
- while(this.syncedViewportElements.length) {
- const viewportElement = this.syncedViewportElements[0];
- this.removeViewportElement(viewportElement);
+ while(this.syncedViewports.length) {
+ const viewport = this.syncedViewports[0];
+ this.removeViewport(viewport);
}
this.active = false;
+ toolManager.deactivateCommandButton('link');
}
update() {
@@ -62,43 +71,68 @@ class StackImagePositionOffsetSynchronizer {
this.activate();
}
+ isViewportSynced(viewportElement) {
+ return !!this.getViewportByElement(viewportElement);
+ }
+
getActiveViewportElement() {
const viewportIndex = Session.get('activeViewport') || 0;
return $('.imageViewerViewport').get(viewportIndex);
}
- isViewportSynced(viewportElement) {
- let isSynced = false;
-
- this.syncedViewportElements.forEach(syncedViewportElement => {
- isSynced = isSynced || (syncedViewportElement === viewportElement);
- });
-
- return isSynced;
- }
-
- removeViewportElement(viewportElement) {
- const index = this.syncedViewportElements.indexOf(viewportElement);
+ removeViewport(viewport) {
+ const index = this.syncedViewports.indexOf(viewport);
if(index === -1) {
return;
}
- this.syncedViewportElements.splice(index, 1);
- this.synchronizer.remove(viewportElement);
- $(viewportElement).off(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT);
+ this.syncedViewports.splice(index, 1);
+ this.synchronizer.remove(viewport.element);
+ this.removeLinkedViewportFromSession(viewport);
+ $(viewport.element).off(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT);
+ }
+
+ getViewportByElement(viewportElement) {
+ const length = this.syncedViewports.length;
+
+ for(let i = 0; i < length; i++) {
+ const viewport = this.syncedViewports[i];
+
+ if(viewport.element === viewportElement) {
+ return viewport;
+ }
+ }
+ }
+
+ removeViewportByElement(viewportElement) {
+ let viewport = this.getViewportByElement(viewportElement);
+
+ if(viewport) {
+ this.removeViewport(viewport);
+ }
+ }
+
+ removeLinkedViewportFromSession(viewport) {
+ const linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports');
+ const index = linkedViewports.indexOf(viewport.index);
+
+ if(index !== -1) {
+ linkedViewports.splice(index, 1);
+ Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', linkedViewports);
+ }
}
elementDisabledHandler(context) {
return (e, eventData) => {
- context.removeViewportElement(eventData.element);
+ context.removeViewportByElement(eventData.element);
}
}
getLinkableViewports() {
const activeViewportElement = this.getActiveViewportElement();
const activeViewportImageNormal = this.getViewportImageNormal(activeViewportElement);
- const viewportElements = [];
+ const viewports = [];
$('.imageViewerViewport').each((index, viewportElement) => {
const viewportImageNormal = this.getViewportImageNormal(viewportElement);
@@ -109,12 +143,15 @@ class StackImagePositionOffsetSynchronizer {
// Pi / 12 radians = 15 degrees
// If the angle between two vectors is Pi, it means they are just inverted
if (angleInRadians < Math.PI / 12 || angleInRadians === Math.PI) {
- viewportElements.push(viewportElement)
+ viewports.push({
+ index: index,
+ element: viewportElement
+ });
}
}
});
- return viewportElements;
+ return viewports;
}
getViewportImageNormal(element) {
diff --git a/Packages/ohif-viewerbase/client/lib/toolManager.js b/Packages/ohif-viewerbase/client/lib/toolManager.js
index 3fbc0b8e0..d55c2b0ba 100644
--- a/Packages/ohif-viewerbase/client/lib/toolManager.js
+++ b/Packages/ohif-viewerbase/client/lib/toolManager.js
@@ -276,6 +276,23 @@ toolManager = {
},
getDefaultTool() {
return defaultTool;
+ },
+ activateCommandButton(button) {
+ const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || [];
+
+ if(activeCommandButtons.indexOf(button) === -1) {
+ activeCommandButtons.push('link');
+ Session.set('ToolManagerActiveCommandButtons', activeCommandButtons);
+ }
+ },
+ deactivateCommandButton(button) {
+ const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || [];
+ const index = activeCommandButtons.indexOf(button);
+
+ if(index !== -1) {
+ activeCommandButtons.splice(index, 1);
+ Session.set('ToolManagerActiveCommandButtons', activeCommandButtons);
+ }
}
};
diff --git a/Packages/ohif-viewerbase/client/lib/viewportFunctions.js b/Packages/ohif-viewerbase/client/lib/viewportFunctions.js
index 1c9928b9b..95cb19e99 100644
--- a/Packages/ohif-viewerbase/client/lib/viewportFunctions.js
+++ b/Packages/ohif-viewerbase/client/lib/viewportFunctions.js
@@ -115,7 +115,7 @@ clearTools = () => {
cornerstone.updateImage(element);
};
-linkStackScroll = () => {
+link = () => {
const synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer;
if(synchronizer.isActive()) {
diff --git a/Packages/ohif-viewerbase/package.js b/Packages/ohif-viewerbase/package.js
index 1c7c5c162..a39d9481e 100644
--- a/Packages/ohif-viewerbase/package.js
+++ b/Packages/ohif-viewerbase/package.js
@@ -297,5 +297,5 @@ Package.onUse(function(api) {
api.export('flipH', 'client');
api.export('rotateR', 'client');
api.export('rotateL', 'client');
- api.export('linkStackScroll', 'client');
+ api.export('link', 'client');
});