Fixed OHIF Viewer layout / CINE / Hanging Protocol buttons (OHIF-49)

This commit is contained in:
Erik Ziegler 2016-07-23 15:56:36 +02:00
parent 59c851fa57
commit 8b364ce9d0
37 changed files with 496 additions and 709 deletions

View File

@ -8,6 +8,9 @@
<div class="pull-right m-t-1 rm-x-1">
{{>roundedButtonGroup rightSidebarToggleButtonData}}
</div>
<div class="pull-right">
{{> toolbarSectionTools toolbarButtons=hangingProtocolButtons}}
</div>
</div>
</div>
</template>

View File

@ -82,6 +82,27 @@ Template.toolbarSection.helpers({
iconClasses: 'fa fa-undo'
});
buttonData.push({
id: 'toggleCinePlay',
title: 'Toggle CINE Play',
classes: 'imageViewerCommand',
buttonTemplateName: 'playClipButton'
});
buttonData.push({
id: 'toggleCineDialog',
title: 'CINE',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-youtube-play'
});
buttonData.push({
id: 'layout',
title: 'Layout',
iconClasses: 'fa fa-th-large',
buttonTemplateName: 'layoutButton'
});
return buttonData;
},
@ -145,6 +166,26 @@ Template.toolbarSection.helpers({
});
return buttonData;
},
hangingProtocolButtons() {
let buttonData = [];
buttonData.push({
id: 'previousPresentationGroup',
title: 'Prev. Stage',
iconClasses: 'fa fa-step-backward',
buttonTemplateName: 'previousPresentationGroupButton'
});
buttonData.push({
id: 'nextPresentationGroup',
title: 'Next Stage',
iconClasses: 'fa fa-step-forward',
buttonTemplateName: 'nextPresentationGroupButton'
});
return buttonData;
}
});
@ -152,6 +193,8 @@ Template.toolbarSection.helpers({
Template.toolbarSection.onRendered(function() {
const instance = Template.instance();
instance.$('#layout').dropdown();
// Set disabled/enabled tool buttons that are set in toolManager
const states = toolManager.getToolDefaultStates();
const disabledToolButtons = states.disabledToolButtons;

View File

@ -2,6 +2,7 @@
{{#if Template.subscriptionsReady}}
<div class="viewerDialogs">
{{> cineDialog}}
{{> layoutChooser }}
</div>
<div id="viewer">
{{> toolbarSection (clone this)}}

View File

@ -1,5 +1,22 @@
import { OHIF } from 'meteor/ohif:core';
OHIF.viewer = OHIF.viewer || {};
OHIF.viewer.loadIndicatorDelay = 500;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
OHIF.viewer.functionList = {
toggleCineDialog: toggleCineDialog,
toggleCinePlay: toggleCinePlay,
clearTools: clearTools,
resetViewport: resetViewport,
invert: invert
};
Session.setDefault('activeViewport', false);
Session.setDefault('leftSidebar', false);
@ -8,9 +25,6 @@ Session.setDefault('rightSidebar', false);
Template.viewer.onCreated(() => {
const instance = Template.instance();
// Attach the Window resize listener
$(window).on('resize', handleResize);
instance.data.state = new ReactiveDict();
instance.data.state.set('leftSidebar', Session.get('leftSidebar'));
instance.data.state.set('rightSidebar', Session.get('rightSidebar'));
@ -19,42 +33,6 @@ Template.viewer.onCreated(() => {
log.info('viewer onCreated');
OHIF.viewer.loadIndicatorDelay = 500;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
OHIF.viewer.functionList = {
invert: element => {
const viewport = cornerstone.getViewport(element);
viewport.invert = !viewport.invert;
cornerstone.setViewport(element, viewport);
},
resetViewport: element => {
const enabledElement = cornerstone.getEnabledElement(element);
if (enabledElement.fitToWindow === false) {
const imageId = enabledElement.image.imageId;
const instance = cornerstoneTools.metaData.get('instance', imageId);
enabledElement.viewport = cornerstone.getDefaultViewport(enabledElement.canvas, enabledElement.image);
const instanceClassDefaultViewport = getInstanceClassDefaultViewport(instance, enabledElement, imageId);
cornerstone.setViewport(element, instanceClassDefaultViewport);
} else {
cornerstone.reset(element);
}
},
clearTools: element => {
const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
toolStateManager.clear(element);
cornerstone.updateImage(element);
}
};
if (isTouchDevice()) {
OHIF.viewer.tooltipConfig = {
trigger: 'manual'
@ -96,27 +74,6 @@ Template.viewer.onCreated(() => {
});
});
Template.viewer.onRendered(() => {
const instance = Template.instance();
// Enable hotkeys
enableHotkeys();
const parentNode = document.getElementById('layoutManagerTarget');
const studies = instance.data.studies;
layoutManager = new LayoutManager(parentNode, studies);
ProtocolEngine = new HP.ProtocolEngine(layoutManager, studies);
HP.setEngine(ProtocolEngine);
});
Template.viewer.onDestroyed(() => {
log.info('onDestroyed');
// Remove the Window resize listener
$(window).off('resize', handleResize);
});
Template.viewer.events({
'click .js-toggle-studies'() {
const instance = Template.instance();

View File

@ -1,20 +0,0 @@
<template name="hangingProtocolButtons">
<button id="previousPresentationGroup" type="button"
class="btn btn-sm"
data-container="body"
data-toggle="tooltip"
data-placement="bottom"
title="Previous presentation group"
disabled="{{ #unless isPreviousAvailable }} true {{ /unless }}">
<span class="fa fa-step-backward"></span>
</button>
<button id="nextPresentationGroup" type="button"
class="btn btn-sm"
data-container="body"
data-toggle="tooltip"
data-placement="bottom"
title="Next presentation group"
disabled="{{ #unless isNextAvailable }} true {{ /unless }}">
<span class="fa fa-step-forward"></span>
</button>
</template>

View File

@ -1,73 +0,0 @@
Template.hangingProtocolButtons.helpers({
/**
* Check if a later stage exists for the user to switch to
*
* @returns {boolean} Whether or not a later stage exists
*/
isNextAvailable: function() {
// Run this helper whenever the ProtocolEngine / LayoutManager has changed
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine has been defined yet, stop here
if (!ProtocolEngine) {
return;
}
// Return whether or not the current stage is the last stage
return ProtocolEngine.stage < ProtocolEngine.getNumProtocolStages() - 1;
},
/**
* Check if an earlier stage exists for the user to switch to
*
* @returns {boolean} Whether or not an earlier stage exists
*/
isPreviousAvailable: function() {
// Run this helper whenever the ProtocolEngine / LayoutManager has changed
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine has been defined yet, stop here
if (!ProtocolEngine) {
return;
}
// Return whether or not the current stage is the first stage
return ProtocolEngine.stage > 0;
}
});
Template.hangingProtocolButtons.events({
/**
* Switch to the previous Presentation group
*
* @param event The click event on the button
*/
'click #previousPresentationGroup': function(event) {
// If no ProtocolEngine has been defined yet, do nothing
if (!ProtocolEngine) {
return;
}
// Hide the button's Bootstrap tooltip in case it was shown
$(event.currentTarget).tooltip('hide');
// Instruct the ProtocolEngine to switch to the next stage
ProtocolEngine.previousProtocolStage();
},
/**
* Switch to the next Presentation group
*
* @param event The click event on the button
*/
'click #nextPresentationGroup': function(event) {
// If no ProtocolEngine has been defined yet, do nothing
if (!ProtocolEngine) {
return;
}
// Hide the button's Bootstrap tooltip in case it was shown
$(event.currentTarget).tooltip('hide');
// Instruct the ProtocolEngine to switch to the next stage
ProtocolEngine.nextProtocolStage();
}
});

View File

@ -6,7 +6,8 @@
aria-haspopup="true"
aria-expanded="false"
title="Select Hanging Protocol">
<i class="fa fa-list-ol"></i><span class="caret"></span>
<i class="fa fa-list-ol"></i>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
@ -14,7 +15,9 @@
</li>
{{ #each matchedProtocols }}
<li>
<a class='matchedProtocol {{#if active}}active{{/if}}'>{{name}}</a>
<a class='matchedProtocol {{#if active}}active{{/if}}'>
{{name}}
</a>
</li>
{{ /each }}
</ul>

View File

@ -0,0 +1,19 @@
<template name="nextPresentationGroupButton">
<div id="{{this.id}}"
class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}} {{ #if nextNotAvailable }}disabled{{ /if }}"
title="{{this.title}}"
disabled="{{ #if nextNotAvailable }}true{{ /if }}">
<div class="svgContainer">
{{ #if this.svgLink }}
<svg>
<use xlink:href={{this.svgLink}}></use>
</svg>
{{ else }}
<i class={{iconClasses}}></i>
{{ /if }}
</div>
<div class="buttonLabel">
{{this.title}}
</div>
</div>
</template>

View File

@ -0,0 +1,39 @@
Template.nextPresentationGroupButton.helpers({
/**
* Check if a later stage exists for the user to switch to
*
* @returns {boolean} Whether or not a later stage exists
*/
nextNotAvailable() {
// Run this helper whenever the ProtocolEngine / LayoutManager has changed
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine has been defined yet, stop here
if (!ProtocolEngine) {
return;
}
// Return whether or not the current stage is the last stage
return ProtocolEngine.stage === ProtocolEngine.getNumProtocolStages() - 1;
}
});
Template.nextPresentationGroupButton.events({
/**
* Switch to the next Presentation group
*
* @param event The click event on the button
*/
'click #nextPresentationGroup'(event) {
// If no ProtocolEngine has been defined yet, do nothing
if (!ProtocolEngine) {
return;
}
// Hide the button's Bootstrap tooltip in case it was shown
$(event.currentTarget).tooltip('hide');
// Instruct the ProtocolEngine to switch to the next stage
ProtocolEngine.nextProtocolStage();
}
});

View File

@ -0,0 +1,19 @@
<template name="previousPresentationGroupButton">
<div id="{{this.id}}"
class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}} {{ #if previousNotAvailable }}disabled{{ /if }}"
title="{{this.title}}"
disabled="{{ #if previousNotAvailable }}true{{ /if }}">
<div class="svgContainer">
{{ #if this.svgLink }}
<svg>
<use xlink:href={{this.svgLink}}></use>
</svg>
{{ else }}
<i class={{iconClasses}}></i>
{{ /if }}
</div>
<div class="buttonLabel">
{{this.title}}
</div>
</div>
</template>

View File

@ -0,0 +1,39 @@
Template.previousPresentationGroupButton.helpers({
/**
* Check if an earlier stage exists for the user to switch to
*
* @returns {boolean} Whether or not an earlier stage exists
*/
previousNotAvailable() {
// Run this helper whenever the ProtocolEngine / LayoutManager has changed
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine has been defined yet, stop here
if (!ProtocolEngine) {
return;
}
// Return whether or not the current stage is the first stage
return ProtocolEngine.stage === 0;
}
});
Template.previousPresentationGroupButton.events({
/**
* Switch to the previous Presentation group
*
* @param event The click event on the button
*/
'click #previousPresentationGroup'(event) {
// If no ProtocolEngine has been defined yet, do nothing
if (!ProtocolEngine) {
return;
}
// Hide the button's Bootstrap tooltip in case it was shown
$(event.currentTarget).tooltip('hide');
// Instruct the ProtocolEngine to switch to the next stage
ProtocolEngine.previousProtocolStage();
}
});

View File

@ -45,8 +45,11 @@ Package.onUse(function(api) {
api.addFiles('client/helpers/attributes.js', 'client');
// UI Components
api.addFiles('client/components/hangingProtocolButtons/hangingProtocolButtons.html', 'client');
api.addFiles('client/components/hangingProtocolButtons/hangingProtocolButtons.js', 'client');
api.addFiles('client/components/previousPresentationGroupButton/previousPresentationGroupButton.html', 'client');
api.addFiles('client/components/previousPresentationGroupButton/previousPresentationGroupButton.js', 'client');
api.addFiles('client/components/nextPresentationGroupButton/nextPresentationGroupButton.html', 'client');
api.addFiles('client/components/nextPresentationGroupButton/nextPresentationGroupButton.js', 'client');
api.addFiles('client/components/matchedProtocols/matchedProtocols.html', 'client');
api.addFiles('client/components/matchedProtocols/matchedProtocols.styl', 'client');

View File

@ -3,20 +3,20 @@
// use this to repopulate the variable
ViewerData = Session.get('ViewerData') || {};
var worklistContentId = 'worklistTab';
var viewerContentId = 'viewerTab';
const worklistContentId = 'worklistTab';
const viewerContentId = 'viewerTab';
Template.lesionTracker.onRendered(function() {
var templateData = Template.currentData();
const templateData = Template.currentData();
if (templateData && templateData.studyInstanceUid) {
var studyInstanceUid = templateData.studyInstanceUid;
const studyInstanceUid = templateData.studyInstanceUid;
openNewTab(studyInstanceUid, studyInstanceUid);
} else {
// If there is a tab set as active in the Session,
// switch to that now.
var contentId = Session.get('activeContentId');
const contentId = Session.get('activeContentId');
// TODO: FIx this it seems to be forcing two switches
// TODO: Fix this it seems to be forcing two switches
switchToTab(contentId);
}
@ -25,7 +25,7 @@ Template.lesionTracker.onRendered(function() {
Template.lesionTracker.events({
'click .js-toggle-studyList': function() {
var contentId = Session.get('activeContentId');
const contentId = Session.get('activeContentId');
if (contentId !== worklistContentId) {
switchToTab(worklistContentId);
@ -39,11 +39,11 @@ Session.set('defaultSignInMessage', 'Tumor tracking in your browser.');
Template.lesionTracker.helpers({
studyListToggleText: function() {
var contentId = Session.get('activeContentId');
const contentId = Session.get('activeContentId');
// If the Viewer has not been opened yet, 'Back to viewer' should
// not be displayed
var viewerContentExists = !!Object.keys(ViewerData).length;
const viewerContentExists = !!Object.keys(ViewerData).length;
if (!viewerContentExists) {
return;
}

View File

@ -2,6 +2,14 @@ import { OHIF } from 'meteor/ohif:core';
import { TimepointApi } from 'meteor/lesiontracker/lib/api/timepoint';
OHIF.viewer = OHIF.viewer || {};
OHIF.viewer.loadIndicatorDelay = 3000;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
Session.setDefault('activeViewport', false);
Session.setDefault('leftSidebar', null);
@ -12,9 +20,6 @@ Template.viewer.onCreated(() => {
instance.data.timepointApi = new TimepointApi();
// Attach the Window resize listener
$(window).on('resize', handleResize);
ValidationErrors.remove({});
instance.data.state = new ReactiveDict();
@ -23,49 +28,20 @@ Template.viewer.onCreated(() => {
Session.set('currentTimepointId', instance.data.currentTimepointId);
var contentId = instance.data.contentId;
const contentId = instance.data.contentId;
OHIF.viewer.loadIndicatorDelay = 3000;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
OHIF.viewer.functionList = {
invert: function(element) {
var viewport = cornerstone.getViewport(element);
viewport.invert = !viewport.invert;
cornerstone.setViewport(element, viewport);
},
resetViewport: function(element) {
cornerstone.reset(element);
},
playClip: function(element) {
var viewportIndex = $('.imageViewerViewport').index(element);
var isPlaying = OHIF.viewer.isPlaying[viewportIndex] || false;
if (isPlaying === true) {
cornerstoneTools.stopClip(element);
} else {
cornerstoneTools.playClip(element);
}
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
Session.set('UpdateCINE', Random.id());
},
OHIF.viewer.functionList = $.extend(OHIF.viewer.functionList, {
toggleLesionTrackerTools: toggleLesionTrackerTools,
clearTools: clearTools,
bidirectional: function() {
bidirectional: () => {
// Used for hotkeys
toolManager.setActiveTool('bidirectional');
},
nonTarget: function() {
nonTarget: () => {
// Used for hotkeys
toolManager.setActiveTool('nonTarget');
}
};
});
// The hotkey can also be an array (e.g. ["NUMPAD0", "0"])
OHIF.viewer.defaultHotkeys = OHIF.viewer.defaultHotkeys || {};
@ -117,23 +93,23 @@ Template.viewer.onCreated(() => {
// Update the ViewerStudies collection with the loaded studies
ViewerStudies.remove({});
instance.data.studies.forEach(function(study) {
instance.data.studies.forEach(study => {
study.selected = true;
ViewerStudies.insert(study);
});
var patientId = instance.data.studies[0].patientId;
const patientId = instance.data.studies[0].patientId;
Session.set('patientId', patientId);
instance.autorun(function() {
var dataContext = Template.currentData();
instance.autorun(() => {
const dataContext = Template.currentData();
instance.subscribe('singlePatientAssociatedStudies', dataContext.studies[0].patientId);
instance.subscribe('singlePatientTimepoints', dataContext.studies[0].patientId);
instance.subscribe('singlePatientMeasurements', dataContext.studies[0].patientId);
instance.subscribe('singlePatientImageMeasurements', dataContext.studies[0].patientId);
instance.subscribe('singlePatientAdditionalFindings', dataContext.studies[0].patientId);
var subscriptionsReady = instance.subscriptionsReady();
const subscriptionsReady = instance.subscriptionsReady();
log.info('autorun viewer.js. Ready: ' + subscriptionsReady);
if (subscriptionsReady) {
@ -143,9 +119,9 @@ Template.viewer.onCreated(() => {
TrialResponseCriteria.validateAllDelayed();
ViewerStudies.find().observe({
added: function(study) {
added: study => {
// Find the relevant timepoint given the newly added study
var timepoint = Timepoints.findOne({
const timepoint = Timepoints.findOne({
studyInstanceUids: {
$in: [study.studyInstanceUid]
}
@ -166,7 +142,7 @@ Template.viewer.onCreated(() => {
});
ImageMeasurements.find().observe({
added: function(data) {
added: data => {
if (data.clientId === ClientId) {
return;
}
@ -176,7 +152,7 @@ Template.viewer.onCreated(() => {
// Update each displayed viewport
updateAllViewports();
},
changed: function(data) {
changed: data => {
if (data.clientId === ClientId) {
return;
}
@ -186,7 +162,7 @@ Template.viewer.onCreated(() => {
// Update each displayed viewport
updateAllViewports();
},
removed: function(data) {
removed: data => {
if (data.clientId === ClientId) {
return;
}
@ -199,7 +175,7 @@ Template.viewer.onCreated(() => {
});
Measurements.find().observe({
added: function(data) {
added: data => {
if (data.clientId === ClientId) {
TrialResponseCriteria.validateAllDelayed();
return;
@ -214,7 +190,7 @@ Template.viewer.onCreated(() => {
// Update each displayed viewport
updateAllViewports();
},
changed: function(data) {
changed: data => {
if (data.clientId === ClientId) {
TrialResponseCriteria.validateAllDelayed();
return;
@ -231,7 +207,7 @@ Template.viewer.onCreated(() => {
TrialResponseCriteria.validateAllDelayed();
},
removed: function(data) {
removed: data => {
log.info('Measurement removed');
// Check that this Measurement actually contains timepoint data
@ -241,14 +217,14 @@ Template.viewer.onCreated(() => {
// Get the Measurement ID and relevant tool so we can remove
// tool data for this Measurement
var measurementId = data._id;
var toolType = data.toolType;
const measurementId = data._id;
const toolType = data.toolType;
// Remove the measurement from all the imageIds on which it exists
// as toolData
Object.keys(data.timepoints).forEach(function(timepointId) {
Object.keys(data.timepoints).forEach(timepointId => {
// Clear the toolData for this timepoint
var imageId = data.timepoints[timepointId].imageId;
const imageId = data.timepoints[timepointId].imageId;
removeToolDataWithMeasurementId(imageId, toolType, measurementId);
// Set reviewer for this timepoint
@ -264,14 +240,14 @@ Template.viewer.onCreated(() => {
// find the Measurements, whereas on the server it's
// only "greater than", since inside this callback the
// Measurements have already been decremented.
var measurements = Measurements.find({
const measurements = Measurements.find({
patientId: data.patientId,
lesionNumberAbsolute: {
$gte: data.lesionNumberAbsolute
}
});
measurements.forEach(function(measurement) {
measurements.forEach(measurement => {
syncMeasurementAndToolData(measurement);
});
@ -289,26 +265,14 @@ Template.viewer.onCreated(() => {
});
});
Template.viewer.onRendered(function() {
// Enable hotkeys
enableHotkeys();
});
Template.viewer.onDestroyed(function() {
// Remove the Window resize listener
$(window).off('resize', handleResize);
OHIF.viewer.updateImageSynchronizer.destroy();
});
Template.viewer.events({
'CornerstoneToolsMeasurementAdded .imageViewerViewport': function(e, template, eventData) {
handleMeasurementAdded(e, eventData);
'CornerstoneToolsMeasurementAdded .imageViewerViewport'(event, instance, eventData) {
handleMeasurementAdded(event, eventData);
},
'CornerstoneToolsMeasurementModified .imageViewerViewport': function(e, template, eventData) {
handleMeasurementModified(e, eventData);
'CornerstoneToolsMeasurementModified .imageViewerViewport'(event, instance, eventData) {
handleMeasurementModified(event, eventData);
},
'CornerstoneToolsMeasurementRemoved .imageViewerViewport': function(e, template, eventData) {
handleMeasurementRemoved(e, eventData);
'CornerstoneToolsMeasurementRemoved .imageViewerViewport'(event, instance, eventData) {
handleMeasurementRemoved(event, eventData);
}
});

View File

@ -1,41 +1,47 @@
<template name="cineDialog">
<div id="cineDialog">
<h5>Cine Controls</h5>
<div id="cineButtons">
<a id="cineFirstButton" title="Skip to first image" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-fast-backward"></i>
<div id="cineDialog" class="noselect">
<h5>CINE Controls</h5>
<div class="btn-group">
<a id="cineFirstButton" title="Skip to first image" class="btn" data-toggle="tooltip">
<i class="fa fa-fast-backward"></i>
</a>
<a id="cineBackButton" title="Previous image" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-step-backward"></i>
<a id="cineBackButton" title="Previous image" class="btn" data-toggle="tooltip">
<i class="fa fa-step-backward"></i>
</a>
<a id="cineSlowPlaybackButton" title="Slow playback" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-backward"></i>
<a id="cineSlowPlaybackButton" title="Slow playback" class="btn" data-toggle="tooltip">
<i class="fa fa-backward"></i>
</a>
<a id="cinePlayButton" title="Play / Pause" class="cineButton" data-toggle="tooltip">
<a id="cinePlayButton" title="Play / Stop" class="btn {{#if isPlaying}}active{{/if}}" data-toggle="tooltip">
{{#if isPlaying}}
<i class="fa fa-lg fa-pause"></i>
<i class="fa fa-fw fa-stop"></i>
{{else}}
<i class="fa fa-lg fa-play"></i>
<i class="fa fa-fw fa-play"></i>
{{/if}}
</a>
<a id="cineFastForwardButton" title="Increase playback speed" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-forward"></i>
<a id="cineFastForwardButton" title="Increase playback speed" class="btn" data-toggle="tooltip">
<i class="fa fa-forward"></i>
</a>
<a id="cineNextButton" title="Next image" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-step-forward"></i>
<a id="cineNextButton" title="Next image" class="btn" data-toggle="tooltip">
<i class="fa fa-step-forward"></i>
</a>
<a id="cineLastButton" title="Skip to last image" class="cineButton" data-toggle="tooltip">
<i class="fa fa-lg fa-fast-forward"></i>
<a id="cineLastButton" title="Skip to last image" class="btn" data-toggle="tooltip">
<i class="fa fa-fast-forward"></i>
</a>
</div>
<div id="cineOptions">
<div id="loopSection">
<label>Loop?</label>
<label for="cineLoopCheckbox">Loop?</label>
<input type="checkbox" checked id="cineLoopCheckbox" />
</div>
<div id="fpsSection">
<label>Cine Speed: <span id="fps">{{framerate}}</span></label>
<input type="range" id="cineSlider" min="1" max="90" value="{{framerate}}"/>
<label for="cineSlider">
Cine Speed: <span id="fps">{{framerate}}</span>
</label>
<input type="range"
id="cineSlider"
min="1"
max="90"
value="{{framerate}}"/>
</div>
</div>
</div>

View File

@ -1,16 +1,5 @@
import { OHIF } from 'meteor/ohif:core';
toggleCinePlay = function() {
var element = getActiveViewportElement();
var playClipToolData = cornerstoneTools.getToolState(element, 'playClip');
if (isPlaying()) {
cornerstoneTools.stopClip(element);
} else {
cornerstoneTools.playClip(element);
}
};
function updateFramerate(rate) {
OHIF.viewer.cine.framesPerSecond = rate;
@ -74,6 +63,7 @@ Template.cineDialog.events({
});
Template.cineDialog.onRendered(function() {
var dialog = $('#cineDialog');
const instance = Template.instance();
const dialog = instance.$('#cineDialog');
dialog.draggable();
});

View File

@ -1,3 +1,7 @@
@import "{design}/app.styl"
$borderColor = rgba(77, 99, 110, 0.81)
#cineDialog
display: none
z-index: 1000
@ -9,32 +13,29 @@
overflow: hidden
padding: 10px
width: 250px
width: 300px
height: 175px
border: 1px black solid
border-radius: 3px
background: white
color: black
opacity: 0.95
border-radius: 8px
border: 1px solid $borderColor;
background: $uiGrayDarkest
color: $textSecondaryColor
h5, label
font-weight: 100
box-sizing: border-box
-webkit-user-select: none
-moz-user-select: none
-o-user-select: none
-ms-user-select: none
-khtml-user-select: none
user-select: none
#cineButtons
padding-bottom: 10px
overflow: auto
.btn
background: $uiGrayDarkest
color: $textSecondaryColor
.cineButton
cursor: pointer
margin: 0 6px
text-decoration: none
&:hover
color: $hoverColor
&:active, &.active
color: $activeColor
#cineOptions
padding: 5px 0

View File

@ -0,0 +1,20 @@
<template name="layoutButton">
<div id="{{this.id}}"
class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}} js-dropdown-toggle"
title="{{this.title}}"
data-target="#layoutChooser"
>
<div class="svgContainer">
{{ #if this.svgLink }}
<svg>
<use xlink:href={{this.svgLink}}></use>
</svg>
{{ else }}
<i class={{iconClasses}}></i>
{{ /if }}
</div>
<div class="buttonLabel">
{{this.title}}
</div>
</div>
</template>

View File

@ -0,0 +1,16 @@
Template.layoutButton.events({
// TODO: Check why 'click' event won't fire?
'mousedown .js-dropdown-toggle'(event) {
// Select the button and it's target dropdown menu
const $button = $(event.currentTarget);
const $dropdown = $($button.data('target'));
// Adjust the dropdown's CSS to properly place it on the page
$dropdown.css({
top: $button.offset().top + $button.outerHeight() + 'px',
left: $button.offset().left + 'px'
});
toggleDialog($dropdown);
}
});

View File

@ -1,5 +1,5 @@
<template name="layoutChooser">
<div class="layoutChooser pull-left dropdown-menu" role="menu">
<div id="layoutChooser" class="layoutChooser pull-left dropdown-menu" role="menu">
<table>
<tr>
<td></td>

View File

@ -6,39 +6,41 @@
* @param currentCell
*/
function highlightCells(currentCell) {
var cells = $('.layoutChooser table td');
const cells = $('.layoutChooser table td');
cells.removeClass('hover');
currentCell = $(currentCell);
var table = currentCell.parents('.layoutChooser table').get(0);
var rowIndex = currentCell.closest('tr').index();
var columnIndex = currentCell.index();
const table = currentCell.parents('.layoutChooser table').get(0);
const rowIndex = currentCell.closest('tr').index();
const columnIndex = currentCell.index();
// Loop through the table row by row
// and cell by cell to apply the highlighting
for (var i = 0; i < table.rows.length; i++) {
row = table.rows[i];
const row = table.rows[i];
if (i <= rowIndex) {
for (var j = 0; j < row.cells.length; j++) {
for (var j = 0; j < row.cells.length; j++) {
if (j <= columnIndex) {
cell = row.cells[j];
const cell = row.cells[j];
cell.classList.add('hover');
}
}
}
}
}
}
Template.layoutChooser.events({
'touchstart .layoutChooser table td, mouseenter .layoutChooser table td': function(evt) {
'touchstart .layoutChooser table td, mouseenter .layoutChooser table td'(evt) {
highlightCells(evt.currentTarget);
},
'click .layoutChooser table td': function(evt) {
var currentCell = $(evt.currentTarget);
var rowIndex = currentCell.closest('tr').index();
var columnIndex = currentCell.index();
'click .layoutChooser table td'(evt) {
const currentCell = $(evt.currentTarget);
const rowIndex = currentCell.closest('tr').index();
const columnIndex = currentCell.index();
// Add 1 because the indices start from zero
var layoutProps = {
const layoutProps = {
rows: rowIndex + 1,
columns: columnIndex + 1
};
@ -46,5 +48,8 @@ Template.layoutChooser.events({
layoutManager.layoutTemplateName = 'gridLayout';
layoutManager.layoutProps = layoutProps;
layoutManager.updateViewports();
const $dropdown = $('.layoutChooser');
toggleDialog($dropdown);
}
});
});

View File

@ -1,19 +1,28 @@
@import "{design}/app.styl"
$borderColor = rgba(77, 99, 110, 0.81)
.layoutChooser
width: 92px
height: 92px
min-width: 92px // to override bootstrap's dropdown-menu class
min-height: 92px
background-color: $primaryBackgroundColor
border: 2px solid $uiBorderColorDark
//background-color: $primaryBackgroundColor
opacity: 0.95
border-radius: 8px
border: 1px solid $borderColor;
background: $uiGrayDarkest
&.open
display: block
table
margin: 0 auto
td
cursor: pointer
border: 2px solid $uiBorderColorDark
border: 1px solid $uiBorderColorDark
width: 20px
height: 20px
transition(background-color 0.1s ease)

View File

@ -14,7 +14,7 @@
p, h4
text-align: center
color: $textColorActive
padding: 4px 0px
padding: 4px 0
p
font-size: 11pt

View File

@ -1,24 +1,20 @@
<template name="playClipButton">
<button id="playClip"
type="button"
class="imageViewerCommand btn btn-sm {{ #if isPlaying }}active{{/if}}"
data-container="body"
data-toggle="tooltip"
data-placement="bottom"
title="Play/Stop Clip">
<div id="{{this.id}}"
class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}} {{ #if isPlaying }}active{{/if}}"
title="{{this.title}}">
<div class="svgContainer">
{{ #if isPlaying }}
<span class="fa fa-stop"></span>
<i class="fa fa-stop fa-fw"></i>
{{ else }}
<span class="fa fa-play"></span>
<i class="fa fa-play fa-fw"></i>
{{ /if }}
</button>
<button id="toggleCineDialog"
type="button"
class="imageViewerCommand btn btn-sm"
data-container="body"
data-toggle="tooltip"
data-placement="bottom"
title="Toggle CINE Dialog">
<span class="fa fa-youtube-play"></span>
</button>
</div>
<div class="buttonLabel">
{{ #if isPlaying }}
Stop
{{ else }}
Play
{{/if}}
</div>
</div>
</template>

View File

@ -1,54 +1,5 @@
import { OHIF } from 'meteor/ohif:core';
toggleCinePlay = function(element) {
var viewports = $('.imageViewerViewport');
if (!element) {
var viewportIndex = Session.get('activeViewport');
element = viewports.get(viewportIndex);
}
if (!element) {
return;
}
var isPlaying = OHIF.viewer.isPlaying[viewportIndex] || false;
if (isPlaying) {
cornerstoneTools.stopClip(element);
} else {
cornerstoneTools.playClip(element);
}
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
Session.set('UpdateCINE', Random.id());
};
isPlaying = function() {
Session.get('UpdateCINE');
var activeViewport = Session.get('activeViewport');
// TODO=Check best way to make sure this is always defined
// Right now it is initialized in enableHotkeys AND in
// imageViewer onCreated, but this appears to break some things
if (!OHIF.viewer.isPlaying) {
return;
}
return !!OHIF.viewer.isPlaying[activeViewport];
};
Template.playClipButton.helpers({
isPlaying: function() {
return isPlaying();
}
});
Template.playClipButton.events({
'click #playClip': function() {
toggleCinePlay();
},
'click #toggleCineDialog': function() {
var cineDialog = document.getElementById('cineDialog');
toggleDialog(cineDialog);
}
});

View File

@ -1,11 +0,0 @@
<template name="simpleToolbarButton">
<button id="{{id}}"
type="button"
class="{{classes}} btn btn-sm {{activeClass}}"
data-container="body"
data-toggle="tooltip"
data-placement="bottom"
title="{{title}}">
<span class="{{iconClasses}}"></span>
</button>
</template>

View File

@ -1,13 +0,0 @@
Template.simpleToolbarButton.helpers({
activeClass() {
const instance = Template.instance();
// Check if the current tool is the active one
if (instance.data.id === Session.get('ToolManagerActiveTool')) {
// Return the active class
return 'active';
}
return;
}
});

View File

@ -1,37 +0,0 @@
<template name="toolbar">
<div class="btn-group">
{{ #each button }}
{{ >simpleToolbarButton}}
{{ /each }}
{{ #if includePlayClipButton }}
{{ >playClipButton }}
{{ /if }}
{{ #if includeLayoutButton }}
<div class="btn-group">
<button id="layout"
type="button"
class="btn btn-sm dropdown-toggle"
data-container="body"
data-toggle="dropdown"
aria-expanded="false"
data-placement="right"
title="Layout"
rel="tooltip">
<span class="fa fa-th-large"></span>
</button>
{{ >layoutChooser }}
</div>
{{ /if }}
{{ #if includeHangingProtocolButtons }}
{{ >hangingProtocolButtons }}
{{ >matchedProtocols }}
{{ /if }}
{{ #each btnGroup }}
{{ >toolbarGroupButton}}
{{ /each }}
</div>
</template>

View File

@ -1,205 +0,0 @@
import { OHIF } from 'meteor/ohif:core';
function getDefaultButtonData() {
var buttonData = [];
buttonData.push({
id: 'wwwc',
title: 'WW/WC',
classes: 'imageViewerTool',
iconClasses: 'fa fa-sun-o'
});
buttonData.push({
id: 'wwwcRegion',
title: 'Window by Region',
classes: 'imageViewerTool',
iconClasses: 'fa fa-square'
});
buttonData.push({
id: 'magnify',
title: 'Magnify',
classes: 'imageViewerTool',
iconClasses: 'fa fa-circle'
});
buttonData.push({
id: 'annotate',
title: 'Annotation',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows-h'
});
buttonData.push({
id: 'invert',
title: 'Invert',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-adjust'
});
buttonData.push({
id: 'zoom',
title: 'Zoom',
classes: 'imageViewerTool',
iconClasses: 'fa fa-search'
});
buttonData.push({
id: 'pan',
title: 'Pan',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows'
});
buttonData.push({
id: 'stackScroll',
title: 'Stack Scroll',
classes: 'imageViewerTool',
iconClasses: 'fa fa-bars'
});
buttonData.push({
id: 'length',
title: 'Length Measurement',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows-v'
});
buttonData.push({
id: 'angle',
title: 'Angle Measurement',
classes: 'imageViewerTool',
iconClasses: 'fa fa-angle-left'
});
buttonData.push({
id: 'dragProbe',
title: 'Pixel Probe',
classes: 'imageViewerTool',
iconClasses: 'fa fa-dot-circle-o'
});
buttonData.push({
id: 'ellipticalRoi',
title: 'Elliptical ROI',
classes: 'imageViewerTool',
iconClasses: 'fa fa-circle-o'
});
buttonData.push({
id: 'rectangleRoi',
title: 'Rectangle ROI',
classes: 'imageViewerTool',
iconClasses: 'fa fa-square-o'
});
buttonData.push({
id: 'resetViewport',
title: 'Reset Viewport',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-undo'
});
buttonData.push({
id: 'clearTools',
title: 'Clear tools',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-trash'
});
return buttonData;
}
Template.toolbar.events({
'click .imageViewerTool': function(e) {
$(e.currentTarget).tooltip('hide');
var tool = e.currentTarget.id;
var elements = $('.imageViewerViewport');
var activeTool = toolManager.getActiveTool();
if (tool === activeTool) {
var defaultTool = toolManager.getDefaultTool();
console.log('Setting active tool to: ' + defaultTool);
toolManager.setActiveTool(defaultTool, elements);
} else {
console.log('Setting active tool to: ' + tool);
toolManager.setActiveTool(tool, elements);
}
},
'click .imageViewerCommand': function(e) {
$(e.currentTarget).tooltip('hide');
var command = e.currentTarget.id;
if (!OHIF.viewer.functionList.hasOwnProperty(command)) {
return;
}
var activeViewport = Session.get('activeViewport');
var element = $('.imageViewerViewport').get(activeViewport);
OHIF.viewer.functionList[command](element);
}
});
Template.toolbar.onRendered(function() {
var tooltipButtons = $('[data-toggle="tooltip"]');
tooltipButtons.tooltip(OHIF.viewer.tooltipConfig);
// Enable tooltips for the layout button
var extraTooltipButtons = $('[rel="tooltip"]');
extraTooltipButtons.tooltip(OHIF.viewer.tooltipConfig);
// Set disabled/enabled tool buttons that are set in toolManager
var states = toolManager.getToolDefaultStates();
var disabledToolButtons = states.disabledToolButtons;
var allToolbarButtons = $('#toolbar').find('button');
if (disabledToolButtons && disabledToolButtons.length > 0) {
for (var i = 0; i < allToolbarButtons.length; i++) {
var toolbarButton = allToolbarButtons[i];
$(toolbarButton).prop('disabled', false);
var index = disabledToolButtons.indexOf($(toolbarButton).attr('id'));
if (index !== -1) {
$(toolbarButton).prop('disabled', true);
}
}
}
});
Template.toolbar.helpers({
button: function() {
if (this.toolbarOptions && this.toolbarOptions.buttonData) {
return this.toolbarOptions.buttonData;
}
return getDefaultButtonData();
},
includePlayClipButton: function() {
if (this.toolbarOptions && this.toolbarOptions.includePlayClipButton !== undefined) {
return this.toolbarOptions.includePlayClipButton;
}
return true;
},
includeLayoutButton: function() {
if (this.toolbarOptions && this.toolbarOptions.includeLayoutButton !== undefined) {
return this.toolbarOptions.includeLayoutButton;
}
return true;
},
includeHangingProtocolButtons: function() {
if (this.toolbarOptions && this.toolbarOptions.includeHangingProtocolButtons !== undefined) {
return this.toolbarOptions.includeHangingProtocolButtons;
}
return true;
},
btnGroup: function() {
if (this.toolbarOptions && this.toolbarOptions.btnGroup !== undefined) {
return this.toolbarOptions.btnGroup;
}
return [];
}
});

View File

@ -1,21 +0,0 @@
@import "{design}/app.styl"
.btn-group
background-color: $primaryBackgroundColor
display: inline-block
button
text-align: center
color: $defaultColor
background-color: $primaryBackgroundColor
border-color: $uiBorderColor
transition(all 0.1s ease)
// Prevent the blue outline in Chrome when a viewport is selected
outline: 0 !important
&:hover
color: $hoverColor
&.active, &:active
color: $activeColor

View File

@ -1,7 +1,12 @@
<template name="toolbarSectionButton">
<div id="{{this.id}}" class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}}" title="{{this.title}}">
{{ #if this.buttonTemplateName }}
{{> UI.dynamic template=this.buttonTemplateName data=this }}
{{ else }}
<div id="{{this.id}}"
class="toolbarSectionButton rp-x-1 {{this.classes}} {{activeClass}}"
title="{{this.title}}">
<div class="svgContainer">
{{ #if this.svgLink }}
{{ #if this.svgLink }}
<svg>
<use xlink:href={{this.svgLink}}></use>
</svg>
@ -13,4 +18,5 @@
{{this.title}}
</div>
</div>
{{ /if }}
</template>

View File

@ -30,7 +30,7 @@ Template.toolbarSectionButton.events({
},
'click .imageViewerCommand'(event, instance) {
const command = event.currentTarget.id;
if (!OHIF.viewer.functionList.hasOwnProperty(command)) {
if (!OHIF.viewer.functionList || !OHIF.viewer.functionList.hasOwnProperty(command)) {
return;
}

View File

@ -4,6 +4,7 @@
{{>toolbarSectionButton toolbarButton}}
{{/each}}
{{ #if extraToolbarButtons}}
<div id="moreTools" class="js-open-more-tools toolbarSectionButton rp-x-1 rm-l-3">
<div class="svgContainer">
<svg>
@ -24,5 +25,6 @@
{{/each}}
</div>
</div>
{{ /if }}
</div>
</template>

View File

@ -1,10 +1,26 @@
Template.viewerMain.onRendered(function() {
var instance = this;
var studies = instance.data.studies;
Template.viewerMain.onCreated(() => {
// Attach the Window resize listener
$(window).on('resize', handleResize);
});
var parentElement = instance.$("#layoutManagerTarget").get(0);
Template.viewerMain.onRendered(() => {
const instance = Template.instance();
const studies = instance.data.studies;
const parentElement = instance.$("#layoutManagerTarget").get(0);
window.layoutManager = new LayoutManager(parentElement, studies);
ProtocolEngine = new HP.ProtocolEngine(window.layoutManager, studies);
HP.setEngine(ProtocolEngine);
// Enable hotkeys
enableHotkeys();
});
Template.viewerMain.onDestroyed(() => {
// Remove the Window resize listener
$(window).off('resize', handleResize);
// Destory the synchronizer used to update reference lines
OHIF.viewer.updateImageSynchronizer.destroy();
});

View File

@ -5,8 +5,8 @@
* @param {Object} study The study instance
*/
sortStudy = function(study) {
if (!study) {
return;
if (!study || !study.seriesList) {
throw "Insufficient study data was provided to sortStudy";
}
study.seriesList.sort(function(a, b) {

View File

@ -4,65 +4,120 @@ getActiveViewportElement = function() {
};
zoomIn = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
viewport.scale += 0.15;
if (viewport.scale > 10.0) {
viewport.scale = 10.0;
}
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
const scaleIncrement = 0.15;
const maximumScale = 10;
viewport.scale = Math.min(viewport.scale + increment, maximumScale);
cornerstone.setViewport(element, viewport);
};
zoomOut = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
viewport.scale -= 0.15;
if (viewport.scale < 0.05) {
viewport.scale = 0.05;
}
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
const scaleIncrement = 0.15;
const minimumScale = 0.05;
viewport.scale = Math.max(viewport.scale - increment, minimumScale);
cornerstone.setViewport(element, viewport);
};
zoomToFit = function() {
var element = getActiveViewportElement();
const element = getActiveViewportElement();
cornerstone.fitToWindow(element);
};
rotateL = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
viewport.rotation -= 90;
cornerstone.setViewport(element, viewport);
updateOrientationMarkers(element, viewport);
};
rotateR = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
viewport.rotation += 90;
cornerstone.setViewport(element, viewport);
updateOrientationMarkers(element, viewport);
};
invert = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
viewport.invert = (viewport.invert === false);
cornerstone.setViewport(element, viewport);
};
flipV = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
viewport.vflip = (viewport.vflip === false);
cornerstone.setViewport(element, viewport);
updateOrientationMarkers(element, viewport);
};
flipH = function() {
var element = getActiveViewportElement();
var viewport = cornerstone.getViewport(element);
const element = getActiveViewportElement();
let viewport = cornerstone.getViewport(element);
viewport.hflip = (viewport.hflip === false);
cornerstone.setViewport(element, viewport);
updateOrientationMarkers(element, viewport);
};
resetViewport = function() {
const element = getActiveViewportElement();
const enabledElement = cornerstone.getEnabledElement(element);
if (enabledElement.fitToWindow === false) {
const imageId = enabledElement.image.imageId;
const instance = cornerstoneTools.metaData.get('instance', imageId);
enabledElement.viewport = cornerstone.getDefaultViewport(enabledElement.canvas, enabledElement.image);
const instanceClassDefaultViewport = getInstanceClassDefaultViewport(instance, enabledElement, imageId);
cornerstone.setViewport(element, instanceClassDefaultViewport);
} else {
cornerstone.reset(element);
}
};
clearTools = function() {
const element = getActiveViewportElement();
const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
toolStateManager.clear(element);
cornerstone.updateImage(element);
};
toggleCinePlay = function() {
const element = getActiveViewportElement();
var viewportIndex = Session.get('activeViewport');
var isPlaying = OHIF.viewer.isPlaying[viewportIndex] || false;
if (isPlaying) {
cornerstoneTools.stopClip(element);
} else {
cornerstoneTools.playClip(element);
}
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
Session.set('UpdateCINE', Random.id());
};
toggleCineDialog = function() {
var cineDialog = document.getElementById('cineDialog');
toggleDialog(cineDialog);
}
isPlaying = function() {
Session.get('UpdateCINE');
var activeViewport = Session.get('activeViewport');
// TODO=Check best way to make sure this is always defined
// Right now it is initialized in enableHotkeys AND in
// imageViewer onCreated, but this appears to break some things
if (!OHIF.viewer.isPlaying) {
return;
}
return !!OHIF.viewer.isPlaying[activeViewport];
};

View File

@ -90,6 +90,9 @@ Package.onUse(function(api) {
api.addFiles('client/components/viewer/imageControls/imageControls.js', 'client');
api.addFiles('client/components/viewer/imageControls/imageControls.styl', 'client');
api.addFiles('client/components/viewer/layoutButton/layoutButton.html', 'client');
api.addFiles('client/components/viewer/layoutButton/layoutButton.js', 'client');
api.addFiles('client/components/viewer/layoutChooser/layoutChooser.html', 'client');
api.addFiles('client/components/viewer/layoutChooser/layoutChooser.js', 'client');
api.addFiles('client/components/viewer/layoutChooser/layoutChooser.styl', 'client');
@ -106,16 +109,9 @@ Package.onUse(function(api) {
api.addFiles('client/components/viewer/toolbarSectionTools/toolbarSectionTools.js', 'client');
api.addFiles('client/components/viewer/toolbarSectionTools/toolbarSectionTools.styl', 'client');
api.addFiles('client/components/viewer/simpleToolbarButton/simpleToolbarButton.html', 'client');
api.addFiles('client/components/viewer/simpleToolbarButton/simpleToolbarButton.js', 'client');
api.addFiles('client/components/viewer/playClipButton/playClipButton.html', 'client');
api.addFiles('client/components/viewer/playClipButton/playClipButton.js', 'client');
api.addFiles('client/components/viewer/toolbar/toolbar.html', 'client');
api.addFiles('client/components/viewer/toolbar/toolbar.js', 'client');
api.addFiles('client/components/viewer/toolbar/toolbar.styl', 'client');
// Library functions
api.addFiles('lib/layoutManager.js', 'client');
api.addFiles('lib/createStacks.js', 'client');
@ -204,6 +200,14 @@ Package.onUse(function(api) {
api.addFiles('lib/helpers/isTouchDevice.js', 'client');
api.export('isTouchDevice', 'client');
// TODO: Clean this up later, no real need to export these
// Need to move functionList into viewerbase
api.export('toggleCineDialog', 'client');
api.export('toggleCinePlay', 'client');
api.export('clearTools', 'client');
api.export('resetViewport', 'client');
api.export('invert', 'client');
api.addFiles('server/methods/importStudies.js', 'server');
api.export('importStudies', 'server');