LT-350: remove measurements from the viewport
This commit is contained in:
parent
9a11dc1808
commit
98e8cf4eca
@ -3,11 +3,13 @@ import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||
export const ToolGroupBaseSchema = new SimpleSchema({
|
||||
toolId: {
|
||||
type: String,
|
||||
label: 'Tool ID'
|
||||
label: 'Tool ID',
|
||||
optional: true
|
||||
},
|
||||
toolItemId: {
|
||||
type: String,
|
||||
label: 'Tool Item ID'
|
||||
label: 'Tool Item ID',
|
||||
optional: true
|
||||
},
|
||||
createdAt: {
|
||||
type: Date
|
||||
|
||||
@ -15,16 +15,8 @@
|
||||
imageId = enabledElement.image.imageId;
|
||||
}
|
||||
|
||||
var enabledElements = cornerstone.getEnabledElementsByImageId(imageId);
|
||||
enabledElements.forEach(function(enabledElement) {
|
||||
var element = enabledElement.element;
|
||||
|
||||
// The HandleMeasurementRemoved handler should do the rest
|
||||
cornerstoneTools.removeToolState(element, toolType, data);
|
||||
|
||||
//Update element
|
||||
cornerstone.updateImage(element);
|
||||
});
|
||||
cornerstoneTools.removeToolState(element, toolType, data);
|
||||
cornerstone.updateImage(element);
|
||||
}
|
||||
|
||||
// TODO = Check if we have the same function already in Cornerstone Tools
|
||||
@ -32,7 +24,7 @@
|
||||
var allTools = toolManager.getTools();
|
||||
var pointNearTool = false;
|
||||
var touchDevice = isTouchDevice();
|
||||
var nearbyTool,
|
||||
var nearbyTool = {},
|
||||
nearbyToolIndex,
|
||||
nearbyToolType;
|
||||
|
||||
@ -54,9 +46,9 @@
|
||||
|
||||
if (toolInterface.pointNearTool(element, data, coords)) {
|
||||
pointNearTool = true;
|
||||
nearbyTool = data;
|
||||
nearbyToolIndex = i;
|
||||
nearbyToolType = toolType;
|
||||
nearbyTool.tool = data;
|
||||
nearbyTool.index = i;
|
||||
nearbyTool.toolType = toolType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -66,17 +58,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
if (pointNearTool === true) {
|
||||
return {
|
||||
nearbyTool: nearbyTool,
|
||||
nearbyToolIndex: nearbyToolIndex,
|
||||
nearbyToolType: nearbyToolType
|
||||
};
|
||||
}
|
||||
return pointNearTool ? nearbyTool : undefined;
|
||||
}
|
||||
|
||||
function keyDownCallback(e, eventData) {
|
||||
var keyCode = eventData.which;
|
||||
|
||||
if (keyCode === keys.DELETE ||
|
||||
(keyCode === keys.D && eventData.event.ctrlKey === true)) {
|
||||
|
||||
@ -87,12 +74,17 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogSettings = {
|
||||
title: 'Delete measurements',
|
||||
message: 'Are you sure you want to delete this measurement?'
|
||||
};
|
||||
|
||||
// TODO= Refactor this so the confirmation dialog is an
|
||||
// optional settable callback in the tool's configuration
|
||||
showConfirmDialog(function() {
|
||||
removeMeasurementTimepoint(nearbyToolData.nearbyTool,
|
||||
nearbyToolData.nearbyToolIndex,
|
||||
nearbyToolData.nearbyToolType,
|
||||
OHIF.ui.showFormDialog('dialogConfirm', dialogSettings).then(() => {
|
||||
removeMeasurementTimepoint(nearbyToolData.tool,
|
||||
nearbyToolData.index,
|
||||
nearbyToolData.toolType,
|
||||
eventData.element
|
||||
);
|
||||
});
|
||||
|
||||
@ -17,7 +17,7 @@ OHIF.lesiontracker.toggleLesionTrackerTools = () => {
|
||||
|
||||
// Hide the tools (set them all to disabled)
|
||||
const toolDefaultStates = {
|
||||
activate: [], //'deleteLesionKeyboardTool'
|
||||
activate: ['deleteLesionKeyboardTool'],
|
||||
deactivate: [],
|
||||
enable: [],
|
||||
disable: [ 'bidirectional', 'nonTarget', 'length', 'targetCR', 'targetUN', 'targetEX' ]
|
||||
|
||||
@ -39,7 +39,7 @@ Meteor.startup(function() {
|
||||
let newDefaultStates = {
|
||||
enable: [ 'scaleOverlayTool' ],
|
||||
deactivate: ['bidirectional', 'nonTarget', 'length', 'targetCR', 'targetUN', 'targetEX'],
|
||||
activate: [] // 'deleteLesionKeyboardTool'
|
||||
activate: ['deleteLesionKeyboardTool']
|
||||
};
|
||||
|
||||
for (let state in newDefaultStates) {
|
||||
|
||||
@ -37,13 +37,37 @@ class MeasurementApi {
|
||||
this.toolsGroupsMap[tool.id] = toolGroup.id;
|
||||
|
||||
const addedHandler = measurement => {
|
||||
let measurementNumber;
|
||||
|
||||
// Get the measurement number
|
||||
const timepoint = this.timepointApi.timepoints.findOne({
|
||||
studyInstanceUids: measurement.studyInstanceUid
|
||||
});
|
||||
const measurementNumber = groupCollection.find({
|
||||
studyInstanceUid: { $in: timepoint.studyInstanceUids }
|
||||
}).count() + 1;
|
||||
|
||||
const emptyItem = groupCollection.findOne({
|
||||
toolId: { $eq: null },
|
||||
timepointId: timepoint.timepointId
|
||||
});
|
||||
|
||||
if (emptyItem) {
|
||||
measurementNumber = emptyItem.measurementNumber;
|
||||
|
||||
groupCollection.update({
|
||||
timepointId: timepoint.timepointId,
|
||||
measurementNumber
|
||||
}, {
|
||||
$set: {
|
||||
toolId: tool.id,
|
||||
toolItemId: measurement._id,
|
||||
createdAt: measurement.createdAt
|
||||
}
|
||||
});
|
||||
} else {
|
||||
measurementNumber = groupCollection.find({
|
||||
studyInstanceUid: { $in: timepoint.studyInstanceUids }
|
||||
}).count() + 1;
|
||||
}
|
||||
|
||||
measurement.measurementNumber = measurementNumber;
|
||||
|
||||
// Get the current location (if already defined)
|
||||
@ -60,16 +84,6 @@ class MeasurementApi {
|
||||
}
|
||||
}
|
||||
|
||||
// Reflect the entry in the tool group collection
|
||||
groupCollection.insert({
|
||||
toolId: tool.id,
|
||||
toolItemId: measurement._id,
|
||||
timepointId: timepoint.timepointId,
|
||||
studyInstanceUid: measurement.studyInstanceUid,
|
||||
createdAt: measurement.createdAt,
|
||||
measurementNumber
|
||||
});
|
||||
|
||||
// Set the timepoint ID, measurement number and location
|
||||
collection.update(measurement._id, {
|
||||
$set: {
|
||||
@ -79,39 +93,74 @@ class MeasurementApi {
|
||||
}
|
||||
});
|
||||
|
||||
if (!emptyItem) {
|
||||
// Reflect the entry in the tool group collection
|
||||
groupCollection.insert({
|
||||
toolId: tool.id,
|
||||
toolItemId: measurement._id,
|
||||
timepointId: timepoint.timepointId,
|
||||
studyInstanceUid: measurement.studyInstanceUid,
|
||||
createdAt: measurement.createdAt,
|
||||
measurementNumber
|
||||
});
|
||||
}
|
||||
|
||||
// Enable reactivity
|
||||
this.changeObserver.changed();
|
||||
};
|
||||
|
||||
const removedHandler = measurement => {
|
||||
// Remove the record from the tools group collection too
|
||||
groupCollection.remove({
|
||||
const measurementNumber = measurement.measurementNumber;
|
||||
|
||||
groupCollection.update({
|
||||
toolItemId: measurement._id
|
||||
}, {
|
||||
$set: {
|
||||
toolId: null,
|
||||
toolItemId: null
|
||||
}
|
||||
});
|
||||
|
||||
// Update the measurement numbers only if it is last item
|
||||
const measurementNumber = measurement.measurementNumber;
|
||||
const timepoint = this.timepointApi.timepoints.findOne({
|
||||
timepointId: measurement.timepointId
|
||||
const nonEmptyItem = groupCollection.findOne({
|
||||
measurementNumber,
|
||||
toolId: { $not: null }
|
||||
});
|
||||
const filter = {
|
||||
studyInstanceUid: { $in: timepoint.studyInstanceUids },
|
||||
measurementNumber
|
||||
};
|
||||
const remainingItems = groupCollection.find(filter).count();
|
||||
if (!remainingItems) {
|
||||
filter.measurementNumber = { $gte: measurementNumber };
|
||||
const operator = {
|
||||
$inc: { measurementNumber: -1 }
|
||||
};
|
||||
const options = { multi: true };
|
||||
groupCollection.update(filter, operator, options);
|
||||
toolGroup.childTools.forEach(childTool => {
|
||||
const collection = this.tools[childTool.id];
|
||||
collection.update(filter, operator, options);
|
||||
});
|
||||
|
||||
if (nonEmptyItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
const groupItems = groupCollection.find({ measurementNumber }).fetch();
|
||||
|
||||
groupItems.forEach(groupItem => {
|
||||
// Remove the record from the tools group collection too
|
||||
groupCollection.remove({ _id: groupItem._id });
|
||||
|
||||
// Update the measurement numbers only if it is last item
|
||||
const timepoint = this.timepointApi.timepoints.findOne({
|
||||
timepointId: groupItem.timepointId
|
||||
});
|
||||
|
||||
const filter = {
|
||||
studyInstanceUid: { $in: timepoint.studyInstanceUids },
|
||||
measurementNumber
|
||||
};
|
||||
|
||||
const remainingItems = groupCollection.find(filter).count();
|
||||
if (!remainingItems) {
|
||||
filter.measurementNumber = { $gte: measurementNumber };
|
||||
const operator = {
|
||||
$inc: { measurementNumber: -1 }
|
||||
};
|
||||
const options = { multi: true };
|
||||
groupCollection.update(filter, operator, options);
|
||||
toolGroup.childTools.forEach(childTool => {
|
||||
const collection = this.tools[childTool.id];
|
||||
collection.update(filter, operator, options);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Enable reactivity
|
||||
this.changeObserver.changed();
|
||||
};
|
||||
@ -258,6 +307,8 @@ class MeasurementApi {
|
||||
// Synchronize the updated measurements with Cornerstone Tools
|
||||
// toolData to make sure the displayed measurements show 'Target X' correctly
|
||||
const syncFilter = _.clone(filter);
|
||||
delete syncFilter.timepointId;
|
||||
|
||||
syncFilter.measurementNumber = {
|
||||
$gt: measurementNumber - 1
|
||||
};
|
||||
@ -281,7 +332,12 @@ class MeasurementApi {
|
||||
const result = [];
|
||||
const items = this.toolGroups[toolGroupId].find(selector, options).fetch();
|
||||
items.forEach(item => {
|
||||
result.push(this.tools[item.toolId].findOne(item.toolItemId));
|
||||
if(item.toolId) {
|
||||
result.push(this.tools[item.toolId].findOne(item.toolItemId));
|
||||
} else {
|
||||
result.push({ measurementNumber: item.measurementNumber });
|
||||
}
|
||||
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -124,7 +124,6 @@ class TimepointApi {
|
||||
});
|
||||
}
|
||||
|
||||
// Return the prior timepoint
|
||||
lock() {
|
||||
const current = this.current();
|
||||
if (!current) {
|
||||
@ -138,6 +137,7 @@ class TimepointApi {
|
||||
});
|
||||
}
|
||||
|
||||
// Return the prior timepoint
|
||||
prior() {
|
||||
const current = this.current();
|
||||
if (!current) {
|
||||
|
||||
@ -70,17 +70,40 @@ Template.measurementTableTimepointCell.events({
|
||||
const rowItem = instance.data.rowItem;
|
||||
const timepoints = instance.data.timepoints.get();
|
||||
OHIF.measurements.jumpToRowItem(rowItem, timepoints);
|
||||
}/*,
|
||||
},
|
||||
|
||||
'keydown .measurementTableTimepointCell'(event, instance) {
|
||||
const keyCode = event.which;
|
||||
if (keyCode === keys.DELETE ||
|
||||
(keyCode === keys.D && e.ctrlKey === true)) {
|
||||
const currentMeasurement = Template.parentData(1).rowItem;
|
||||
const currentTimepointID = this.timepointId;
|
||||
|
||||
showConfirmDialog(function() {
|
||||
OHIF.lesiontracker.clearMeasurementTimepointData(currentMeasurement._id, currentTimepointID);
|
||||
if (keyCode === keys.DELETE || keyCode === keys.BACKSPACE || (keyCode === keys.D && event.ctrlKey === true)) {
|
||||
const currentMeasurement = Template.parentData(1).rowItem;
|
||||
const timepointId = this.timepointId;
|
||||
|
||||
const dialogSettings = {
|
||||
title: 'Delete measurements',
|
||||
message: 'Are you sure you want to delete this measurement?'
|
||||
};
|
||||
|
||||
OHIF.ui.showFormDialog('dialogConfirm', dialogSettings).then(() => {
|
||||
const measurementTypeId = instance.data.rowItem.measurementTypeId;
|
||||
const measurement = instance.data.rowItem.entries[0];
|
||||
const measurementNumber = measurement.measurementNumber;
|
||||
const measurementApi = instance.data.measurementApi;
|
||||
const timepointApi = instance.data.timepointApi;
|
||||
|
||||
// Remove all the measurements with the given type and number
|
||||
measurementApi.deleteMeasurements(measurementTypeId, {
|
||||
measurementNumber,
|
||||
timepointId
|
||||
});
|
||||
|
||||
// Sync the new measurement data with cornerstone tools
|
||||
const baseline = timepointApi.baseline();
|
||||
measurementApi.sortMeasurements(baseline.timepointId);
|
||||
|
||||
// Repaint the images on all viewports without the removed measurements
|
||||
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
|
||||
});
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
|
||||
theme('color', '$textPrimaryColor')
|
||||
padding: 0 10px
|
||||
outline: none
|
||||
cursor: pointer
|
||||
|
||||
&:hover
|
||||
|
||||
@ -114,11 +114,26 @@ class MeasurementHandlers {
|
||||
static onRemoved(e, instance, eventData) {
|
||||
OHIF.log.info('CornerstoneToolsMeasurementRemoved');
|
||||
const measurementData = eventData.measurementData;
|
||||
const measurementNumber = measurementData.measurementNumber;
|
||||
const measurementApi = instance.data.measurementApi;
|
||||
const Collection = measurementApi.tools[eventData.toolType];
|
||||
const timepointApi = instance.data.timepointApi;
|
||||
const collection = measurementApi.tools[eventData.toolType];
|
||||
const measurementTypeId = measurementApi.toolsGroupsMap[measurementData.toolType];
|
||||
const measurement = collection.findOne(measurementData._id);
|
||||
const timepointId = measurement.timepointId;
|
||||
|
||||
// Remove the measurement from the collection
|
||||
Collection.remove(measurementData._id);
|
||||
// Remove all the measurements with the given type and number
|
||||
measurementApi.deleteMeasurements(measurementTypeId, {
|
||||
measurementNumber,
|
||||
timepointId
|
||||
});
|
||||
|
||||
// Sync the new measurement data with cornerstone tools
|
||||
const baseline = timepointApi.baseline();
|
||||
measurementApi.sortMeasurements(baseline.timepointId);
|
||||
|
||||
// Repaint the images on all viewports without the removed measurements
|
||||
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
|
||||
|
||||
// Signal unsaved changes
|
||||
OHIF.ui.unsavedChanges.set('viewer.studyViewer.measurements.' + eventData.toolType);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user