Added hotkey support to viewerbase
This commit is contained in:
1 parent
a005e5b359
commit
da3101be93
59 files changed
+1002
-71
No files matched your search
@@ -0,0 +1,10 @@
|
||||
<template name="imageThumbnail">
|
||||
<div class="imageThumbnail">
|
||||
<div class="imageThumbnailLoadingIndicator thumbnailLoadingIndicator">
|
||||
<p>Loading {{percentComplete}}</p>
|
||||
</div>
|
||||
<div class="imageThumbnailErrorLoadingIndicator thumbnailLoadingIndicator">
|
||||
<p>Error</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,37 @@
|
||||
Template.imageThumbnail.onRendered(function() {
|
||||
var instance = this.data.stack.instances[0];
|
||||
var element = this.find('.imageThumbnail');
|
||||
|
||||
cornerstone.disable(element);
|
||||
$(element).find('canvas').remove();
|
||||
|
||||
cornerstone.enable(element);
|
||||
|
||||
var imageId = getImageId(instance);
|
||||
|
||||
var elem = $(element);
|
||||
elem.find('.imageThumbnailLoadingIndicator').css('display', 'block');
|
||||
|
||||
var thumbnailIndex = $('.imageThumbnail').index(element);
|
||||
ThumbnailLoading[thumbnailIndex] = imageId;
|
||||
|
||||
this.data.thumbnailIndex = thumbnailIndex;
|
||||
|
||||
cornerstone.loadAndCacheImage(imageId).then(function(image) {
|
||||
cornerstone.displayImage(element, image);
|
||||
|
||||
delete ThumbnailLoading[thumbnailIndex];
|
||||
elem.find('.imageThumbnailLoadingIndicator').css('display', 'none');
|
||||
}, function(error) {
|
||||
elem.find('.imageThumbnailErrorLoadingIndicator').css('display', 'block');
|
||||
});
|
||||
});
|
||||
|
||||
Template.imageThumbnail.helpers({
|
||||
'percentComplete': function() {
|
||||
var percentComplete = Session.get('CornerstoneThumbnailLoadProgress' + this.thumbnailIndex);
|
||||
if (percentComplete && percentComplete !== 100) {
|
||||
return percentComplete + '%';
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
.imageThumbnail
|
||||
width: 90px
|
||||
height: 90px
|
||||
background-color: black
|
||||
margin: 0 auto
|
||||
position: relative
|
||||
|
||||
.thumbnailLoadingIndicator
|
||||
display: none
|
||||
pointer-events: none
|
||||
color: #f8a13f
|
||||
height: 20px
|
||||
width: 100%
|
||||
top: 0
|
||||
left: 0
|
||||
right: 0
|
||||
bottom: 0
|
||||
margin: auto
|
||||
position: absolute
|
||||
|
||||
p
|
||||
text-align: center
|
||||
font-size: 10pt
|
||||
@@ -0,0 +1,7 @@
|
||||
<template name="studyBrowser">
|
||||
<div class="studyBrowser">
|
||||
{{ #each studies }}
|
||||
{{ >thumbnails }}
|
||||
{{ /each }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
Template.studyBrowser.helpers({
|
||||
studies : function() {
|
||||
return ViewerStudies.find({selected: true});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
.studyBrowser
|
||||
float: left
|
||||
height: 100%
|
||||
width: 100%
|
||||
min-width: 120px
|
||||
overflow-y: auto
|
||||
overflow-x: hidden
|
||||
background-color: black
|
||||
padding-bottom: 20px
|
||||
@@ -0,0 +1,6 @@
|
||||
<template name="thumbnailEntry">
|
||||
<div class="thumbnailEntry">
|
||||
{{ >imageThumbnail }}
|
||||
<div class='seriesDescription noselect'>{{seriesDescription}}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,220 @@
|
||||
function cloneElement(element, targetId) {
|
||||
// Clone the DOM element
|
||||
var clone = element.cloneNode(true);
|
||||
|
||||
// Find any canvas children to clone
|
||||
var clonedCanvases = $(clone).find('canvas');
|
||||
clonedCanvases.each(function(canvasIndex, clonedCanvas) {
|
||||
// Draw from the original canvas to the cloned canvas
|
||||
var context = clonedCanvas.getContext('2d');
|
||||
var thumbnailCanvas = $(element).find('canvas').get(canvasIndex);
|
||||
context.drawImage(thumbnailCanvas, 0, 0);
|
||||
});
|
||||
|
||||
// Update the clone with the targetId
|
||||
clone.id = targetId;
|
||||
clone.style.visibility = 'hidden';
|
||||
return clone;
|
||||
}
|
||||
|
||||
function thumbnailDragStartHandler(e, data) {
|
||||
// Prevent any scrolling behaviour normally caused by the original event
|
||||
e.originalEvent.preventDefault();
|
||||
|
||||
// Identify the current study and series index from the thumbnail's DOM position
|
||||
var targetThumbnail = e.currentTarget;
|
||||
var imageThumbnail = $(targetThumbnail);
|
||||
|
||||
// Store this data for use during drag and drop
|
||||
OHIF.viewer.dragAndDropData = data;
|
||||
|
||||
// Clone the image thumbnail
|
||||
var targetId = targetThumbnail.id + 'DragClone';
|
||||
var clone = cloneElement(targetThumbnail, targetId);
|
||||
clone.classList.add('imageThumbnailClone');
|
||||
|
||||
// Set pointerEvents to pass through the clone DOM element
|
||||
// This is necessary in order to identify what is below it
|
||||
// when using document.elementFromPoint
|
||||
clone.style.pointerEvents = "none";
|
||||
|
||||
// Append the clone to the parent of the target
|
||||
targetThumbnail.parentNode.appendChild(clone);
|
||||
|
||||
// Set the cursor x and y positions from the current touch/mouse coordinates
|
||||
// Handle touchStart cases
|
||||
if (e.type === 'touchstart') {
|
||||
cursorX = e.originalEvent.touches[0].pageX;
|
||||
cursorY = e.originalEvent.touches[0].pageY;
|
||||
} else {
|
||||
cursorX = e.pageX;
|
||||
cursorY = e.pageY;
|
||||
|
||||
// Also hook up event handlers for mouse events
|
||||
$(document).on('mousemove', function(e) {
|
||||
thumbnailDragHandler(e, targetThumbnail);
|
||||
});
|
||||
$(document).on('mouseup', function(e) {
|
||||
thumbnailDragEndHandler(e, targetThumbnail);
|
||||
});
|
||||
}
|
||||
|
||||
// This block gets the current position of the touch/mouse
|
||||
// relative to the thumbnail itself
|
||||
//
|
||||
// i.e. Where did the user grab it from?
|
||||
var position = imageThumbnail.offset();
|
||||
var left = position.left;
|
||||
var top = position.top;
|
||||
|
||||
// This difference is saved for later so the element movement looks normal
|
||||
diffX = cursorX - left;
|
||||
diffY = cursorY - top;
|
||||
|
||||
// This sets the default style properties of the cloned element so it is
|
||||
// ready to be dragged around the page
|
||||
$(clone).css({
|
||||
top: top,
|
||||
left: left,
|
||||
position: 'absolute',
|
||||
'z-index': 100,
|
||||
visibility: 'hidden'
|
||||
});
|
||||
}
|
||||
|
||||
function thumbnailDragHandler(e, target) {
|
||||
// Get the touch/mouse coordinates from the event
|
||||
var cursorX,
|
||||
cursorY;
|
||||
if (e.type === 'touchmove') {
|
||||
cursorX = e.originalEvent.changedTouches[0].pageX;
|
||||
cursorY = e.originalEvent.changedTouches[0].pageY;
|
||||
} else {
|
||||
cursorX = e.pageX;
|
||||
cursorY = e.pageY;
|
||||
}
|
||||
|
||||
// Find the clone element and update it's position on the page
|
||||
var clone = $('#' + target.id + 'DragClone');
|
||||
clone.css({
|
||||
top: cursorY - diffY,
|
||||
left: cursorX - diffX,
|
||||
position: 'absolute',
|
||||
'z-index': 100,
|
||||
visibility: 'visible'
|
||||
});
|
||||
|
||||
// Identify the element below the current cursor position
|
||||
var elemBelow = document.elementFromPoint(cursorX + diffX, cursorY + diffY);
|
||||
|
||||
// If none exists, stop here
|
||||
if (!elemBelow) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any current faded effects on viewports
|
||||
$('.imageViewerViewport canvas').removeClass('faded');
|
||||
|
||||
// Figure out what to do depending on what we're dragging over
|
||||
var viewportsDraggedOver = $(elemBelow).parents('.imageViewerViewport');
|
||||
if (viewportsDraggedOver.length) {
|
||||
// If we're dragging over a non-empty viewport, fade it and change the cursor style
|
||||
viewportsDraggedOver.find('canvas').not('.magnifyTool').addClass('faded');
|
||||
document.body.style.cursor = "copy";
|
||||
} else if (elemBelow.classList.contains('imageViewerViewport') && elemBelow.classList.contains('empty')) {
|
||||
// If we're dragging over an empty viewport, just change the cursor style
|
||||
document.body.style.cursor = "copy";
|
||||
} else {
|
||||
// Otherwise, keep the cursor as no-drop style
|
||||
document.body.style.cursor = "no-drop";
|
||||
}
|
||||
}
|
||||
|
||||
function thumbnailDragEndHandler(e, target) {
|
||||
// Remove the mouse event listeners
|
||||
$(document).off('mousemove mouseup');
|
||||
|
||||
// Reset the cursor style to the default
|
||||
document.body.style.cursor = "auto";
|
||||
|
||||
// Get the cloned element
|
||||
var clone = $('#' + target.id + 'DragClone');
|
||||
|
||||
// If it doesn't exist, stop here
|
||||
if (!clone.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var top = clone.offset().top;
|
||||
var left = clone.offset().left;
|
||||
|
||||
// Identify the element below the cloned element position
|
||||
var elemBelow = document.elementFromPoint(left + diffX, top + diffY);
|
||||
|
||||
// Remove all cloned elements from the page
|
||||
$('.imageThumbnailClone').remove();
|
||||
|
||||
// Remove any current faded effects on viewports
|
||||
$('.imageViewerViewport canvas').removeClass('faded');
|
||||
|
||||
// If none exists, stop here
|
||||
if (!elemBelow) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any fade effects on the element below
|
||||
elemBelow.classList.remove('faded');
|
||||
|
||||
var element;
|
||||
var viewportsDraggedOver = $(elemBelow).parents('.imageViewerViewport');
|
||||
if (viewportsDraggedOver.length) {
|
||||
// If we're dragging over a non-empty viewport, retrieve it
|
||||
element = viewportsDraggedOver.get(0);
|
||||
} else if (elemBelow.classList.contains('imageViewerViewport') &&
|
||||
elemBelow.classList.contains('empty')) {
|
||||
// If we're dragging over an empty viewport, retrieve that instead
|
||||
element = elemBelow;
|
||||
} else {
|
||||
// Otherwise, stop here
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no store drag and drop data, stop here
|
||||
if (!OHIF.viewer.dragAndDropData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rerender the viewport using the drag and drop data
|
||||
rerenderViewportWithNewSeries(element, OHIF.viewer.dragAndDropData);
|
||||
Session.get('UseHangingProtocol', false);
|
||||
return false;
|
||||
}
|
||||
|
||||
Template.thumbnailEntry.onRendered(function() {
|
||||
var entry = this.find('.thumbnailEntry');
|
||||
$(entry).data('seriesInstanceUid', Template.parentData(0).seriesInstanceUid);
|
||||
$(entry).data('studyInstanceUid', Template.parentData(1).studyInstanceUid);
|
||||
});
|
||||
|
||||
Template.thumbnailEntry.events({
|
||||
// Touch drag/drop events
|
||||
'touchstart .thumbnailEntry, mousedown .thumbnailEntry': function(e) {
|
||||
var data = {
|
||||
studyInstanceUid: this.stack.studyInstanceUid,
|
||||
seriesInstanceUid: this.stack.seriesInstanceUid
|
||||
};
|
||||
thumbnailDragStartHandler(e, data);
|
||||
},
|
||||
'touchmove .thumbnailEntry': function(e) {
|
||||
thumbnailDragHandler(e, e.currentTarget);
|
||||
},
|
||||
'touchend .thumbnailEntry': function(e){
|
||||
thumbnailDragEndHandler(e, e.currentTarget);
|
||||
}
|
||||
});
|
||||
|
||||
Template.thumbnailEntry.helpers({
|
||||
seriesDescription : function() {
|
||||
return this.stack.seriesDescription || '';
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
.thumbnailEntry
|
||||
width: 105px
|
||||
padding: 5px
|
||||
background-color: black
|
||||
border: 1px solid #424242
|
||||
margin: 0 auto
|
||||
cursor: copy
|
||||
cursor: -webkit-grab
|
||||
cursor: -moz-grab
|
||||
|
||||
.seriesDescription
|
||||
text-align: center
|
||||
color: #555
|
||||
word-wrap: break-word
|
||||
|
||||
&:hover
|
||||
background-color: white
|
||||
|
||||
&.active
|
||||
background-color: #424242
|
||||
border-color: #4e4e4e
|
||||
|
||||
.seriesDescription
|
||||
color: white
|
||||
@@ -0,0 +1,5 @@
|
||||
<template name="thumbnails">
|
||||
{{#each thumbnails}}
|
||||
{{ >thumbnailEntry }}
|
||||
{{/each}}
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
Template.thumbnails.helpers({
|
||||
thumbnails: function() {
|
||||
var study = this;
|
||||
var stacks = createStacks(study);
|
||||
|
||||
var array = [];
|
||||
stacks.forEach(function(stack, index) {
|
||||
array.push({
|
||||
thumbnailIndex: index,
|
||||
stack: stack
|
||||
});
|
||||
});
|
||||
return array;
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user