PWV-138: Rendering handles and lines based on handles' state
This commit is contained in:
parent
e330973c1e
commit
0888e08536
@ -145,9 +145,6 @@ function addNewMeasurement(mouseEventData) {
|
|||||||
// Bind a one-time event listener for the Esc key
|
// Bind a one-time event listener for the Esc key
|
||||||
$(element).one('keydown', cancelCallback);
|
$(element).one('keydown', cancelCallback);
|
||||||
|
|
||||||
// Make handle invisible while moving
|
|
||||||
measurementData.handles.end.drawnIndependently = true;
|
|
||||||
|
|
||||||
cornerstone.updateImage(element);
|
cornerstone.updateImage(element);
|
||||||
|
|
||||||
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
|
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
|
||||||
@ -165,9 +162,6 @@ function addNewMeasurement(mouseEventData) {
|
|||||||
// perpendicular line is not connected to long-line
|
// perpendicular line is not connected to long-line
|
||||||
measurementData.handles.perpendicularStart.locked = false;
|
measurementData.handles.perpendicularStart.locked = false;
|
||||||
|
|
||||||
// Enable handle visibility again
|
|
||||||
measurementData.handles.end.drawnIndependently = false;
|
|
||||||
|
|
||||||
$(element).on('CornerstoneToolsMouseMove', eventData, mouseMoveCallback);
|
$(element).on('CornerstoneToolsMouseMove', eventData, mouseMoveCallback);
|
||||||
$(element).on('CornerstoneToolsMouseDown', eventData, mouseDownCallback);
|
$(element).on('CornerstoneToolsMouseDown', eventData, mouseDownCallback);
|
||||||
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.bidirectional.mouseDownActivateCallback);
|
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.bidirectional.mouseDownActivateCallback);
|
||||||
@ -673,18 +667,59 @@ function setHandlesVisible (handles, isVisibile) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Clear the selected state for the given handles object
|
||||||
function unselectAllHandles(handles) {
|
function unselectAllHandles(handles) {
|
||||||
|
let imageNeedsUpdate = false;
|
||||||
Object.keys(handles).forEach(handleKey => {
|
Object.keys(handles).forEach(handleKey => {
|
||||||
if (handleKey === 'textBox') return;
|
if (handleKey === 'textBox') return;
|
||||||
handles[handleKey].selected = false;
|
handles[handleKey].selected = false;
|
||||||
|
imageNeedsUpdate = handles[handleKey].active || imageNeedsUpdate;
|
||||||
handles[handleKey].active = false;
|
handles[handleKey].active = false;
|
||||||
});
|
});
|
||||||
|
return imageNeedsUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the bidirectional tool's selection for all tool handles
|
||||||
|
function clearBidirectionalSelection(event) {
|
||||||
|
let imageNeedsUpdate = false;
|
||||||
|
const toolData = cornerstoneTools.getToolState(event.currentTarget, 'bidirectional');
|
||||||
|
if (!toolData) return;
|
||||||
|
toolData.data.forEach(data => {
|
||||||
|
data.selected = false;
|
||||||
|
imageNeedsUpdate = data.active || imageNeedsUpdate;
|
||||||
|
data.active = false;
|
||||||
|
const unselectResult = unselectAllHandles(data.handles);
|
||||||
|
imageNeedsUpdate = imageNeedsUpdate || unselectResult;
|
||||||
|
});
|
||||||
|
return imageNeedsUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replaces the cornerstoneTools.handleActivator function by skiping the active handle comparison
|
||||||
|
function handleActivator(element, handles, canvasPoint, distanceThreshold=6) {
|
||||||
|
const nearbyHandle = cornerstoneTools.getHandleNearImagePoint(element, handles, canvasPoint, distanceThreshold);
|
||||||
|
|
||||||
|
let handleActivatorChanged = false;
|
||||||
|
Object.keys(handles).forEach(handleKey => {
|
||||||
|
if (handleKey === 'textBox') return;
|
||||||
|
const handle = handles[handleKey];
|
||||||
|
const newActiveState = handle === nearbyHandle;
|
||||||
|
if (handle.active !== newActiveState) {
|
||||||
|
handleActivatorChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.active = newActiveState;
|
||||||
|
});
|
||||||
|
|
||||||
|
return handleActivatorChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a proxy to cornerstoneTools.drawHandles function to change the handles' active state base on
|
||||||
|
// the hover, moving and selected states
|
||||||
function drawHandles(context, eventData, handles, color, options) {
|
function drawHandles(context, eventData, handles, color, options) {
|
||||||
Object.keys(handles).forEach(handleKey => {
|
Object.keys(handles).forEach(handleKey => {
|
||||||
if (handleKey === 'textBox') return;
|
if (handleKey === 'textBox') return;
|
||||||
const handle = handles[handleKey];
|
const handle = handles[handleKey];
|
||||||
|
handle.drawnIndependently = handle.moving;
|
||||||
if (handle.selected) {
|
if (handle.selected) {
|
||||||
handle.active = true;
|
handle.active = true;
|
||||||
} else {
|
} else {
|
||||||
@ -699,11 +734,6 @@ function drawHandles(context, eventData, handles, color, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function moveHandle(mouseEventData, toolType, data, handle, doneMovingCallback, preventHandleOutsideImage) {
|
function moveHandle(mouseEventData, toolType, data, handle, doneMovingCallback, preventHandleOutsideImage) {
|
||||||
// Make handle invisible while moving
|
|
||||||
if (!handle.hasBoundingBox) {
|
|
||||||
handle.drawnIndependently = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var element = mouseEventData.element;
|
var element = mouseEventData.element;
|
||||||
var distanceFromTool = {
|
var distanceFromTool = {
|
||||||
x: handle.x - mouseEventData.currentPoints.image.x,
|
x: handle.x - mouseEventData.currentPoints.image.x,
|
||||||
@ -742,10 +772,6 @@ function moveHandle(mouseEventData, toolType, data, handle, doneMovingCallback,
|
|||||||
$(element).on('CornerstoneToolsMouseDrag', mouseDragCallback);
|
$(element).on('CornerstoneToolsMouseDrag', mouseDragCallback);
|
||||||
|
|
||||||
function mouseUpCallback() {
|
function mouseUpCallback() {
|
||||||
// Enable handle visibility again
|
|
||||||
if (!handle.hasBoundingBox) {
|
|
||||||
handle.drawnIndependently = false;
|
|
||||||
}
|
|
||||||
$(element).off('CornerstoneToolsMouseDrag', mouseDragCallback);
|
$(element).off('CornerstoneToolsMouseDrag', mouseDragCallback);
|
||||||
$(element).off('CornerstoneToolsMouseUp', mouseUpCallback);
|
$(element).off('CornerstoneToolsMouseUp', mouseUpCallback);
|
||||||
$(element).off('CornerstoneToolsMouseClick', mouseUpCallback);
|
$(element).off('CornerstoneToolsMouseClick', mouseUpCallback);
|
||||||
@ -782,13 +808,13 @@ function mouseMoveCallback(e, eventData) {
|
|||||||
var coords = eventData.currentPoints.canvas;
|
var coords = eventData.currentPoints.canvas;
|
||||||
|
|
||||||
var data = toolData.data[i];
|
var data = toolData.data[i];
|
||||||
const handleActivatorChanged = cornerstoneTools.handleActivator(eventData.element, data.handles, coords);
|
const handleActivatorChanged = handleActivator(eventData.element, data.handles, coords);
|
||||||
Object.keys(data.handles).forEach(handleKey => {
|
Object.keys(data.handles).forEach(handleKey => {
|
||||||
if (handleKey === 'textBox') return;
|
if (handleKey === 'textBox') return;
|
||||||
const handle = data.handles[handleKey];
|
const handle = data.handles[handleKey];
|
||||||
handle.hover = handle.active;
|
handle.hover = handle.active;
|
||||||
});
|
});
|
||||||
if (handleActivatorChanged === true) {
|
if (handleActivatorChanged) {
|
||||||
imageNeedsUpdate = true;
|
imageNeedsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,6 +835,15 @@ function mouseDownCallback(e, eventData) {
|
|||||||
var data;
|
var data;
|
||||||
var element = eventData.element;
|
var element = eventData.element;
|
||||||
|
|
||||||
|
// Clear selection on left mouse button click
|
||||||
|
let imageNeedsUpdate = false;
|
||||||
|
if (eventData.which === 1) {
|
||||||
|
const imageNeedsUpdate = clearBidirectionalSelection(e);
|
||||||
|
if (imageNeedsUpdate) {
|
||||||
|
cornerstone.updateImage(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleDoneMove(handle) {
|
function handleDoneMove(handle) {
|
||||||
// Set the cursor back to its default
|
// Set the cursor back to its default
|
||||||
$(element).css('cursor', '');
|
$(element).css('cursor', '');
|
||||||
@ -842,8 +877,8 @@ function mouseDownCallback(e, eventData) {
|
|||||||
var distance = 6;
|
var distance = 6;
|
||||||
var handle = cornerstoneTools.getHandleNearImagePoint(element, data.handles, coords, distance);
|
var handle = cornerstoneTools.getHandleNearImagePoint(element, data.handles, coords, distance);
|
||||||
if (handle) {
|
if (handle) {
|
||||||
// Hide the cursor to improve precision while resizing the line
|
// Hide the cursor to improve precision while resizing the line or set to move if dragging text box
|
||||||
$(element).css('cursor', 'none');
|
$(element).css('cursor', handle.hasBoundingBox ? 'move' : 'none');
|
||||||
|
|
||||||
$(element).off('CornerstoneToolsMouseMove', mouseMoveCallback);
|
$(element).off('CornerstoneToolsMouseMove', mouseMoveCallback);
|
||||||
data.active = true;
|
data.active = true;
|
||||||
@ -851,7 +886,6 @@ function mouseDownCallback(e, eventData) {
|
|||||||
|
|
||||||
unselectAllHandles(data.handles);
|
unselectAllHandles(data.handles);
|
||||||
handle.moving = true;
|
handle.moving = true;
|
||||||
handle.selected = true;
|
|
||||||
moveHandle(eventData, toolType, data, handle, () => handleDoneMove(handle));
|
moveHandle(eventData, toolType, data, handle, () => handleDoneMove(handle));
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
return false;
|
return false;
|
||||||
@ -870,6 +904,9 @@ function mouseDownCallback(e, eventData) {
|
|||||||
for (i = 0; i < toolData.data.length; i++) {
|
for (i = 0; i < toolData.data.length; i++) {
|
||||||
data = toolData.data[i];
|
data = toolData.data[i];
|
||||||
if (pointNearTool(element, data, coords)) {
|
if (pointNearTool(element, data, coords)) {
|
||||||
|
// Set the cursor to move
|
||||||
|
$(element).css('cursor', 'move');
|
||||||
|
|
||||||
$(element).off('CornerstoneToolsMouseMove', mouseMoveCallback);
|
$(element).off('CornerstoneToolsMouseMove', mouseMoveCallback);
|
||||||
data.active = true;
|
data.active = true;
|
||||||
data.selected = true;
|
data.selected = true;
|
||||||
@ -1039,8 +1076,9 @@ function onImageRendered(e, eventData) {
|
|||||||
context.shadowOffsetY = config.shadowOffsetY || 1;
|
context.shadowOffsetY = config.shadowOffsetY || 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const activeColor = cornerstoneTools.toolColors.getActiveColor();
|
||||||
if (data.active) {
|
if (data.active) {
|
||||||
color = cornerstoneTools.toolColors.getActiveColor();
|
color = activeColor;
|
||||||
} else {
|
} else {
|
||||||
color = cornerstoneTools.toolColors.getToolColor();
|
color = cornerstoneTools.toolColors.getToolColor();
|
||||||
}
|
}
|
||||||
@ -1050,18 +1088,27 @@ function onImageRendered(e, eventData) {
|
|||||||
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
|
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
|
||||||
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
|
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
|
||||||
|
|
||||||
|
let lineColor;
|
||||||
|
if (!data.active && (data.handles.start.selected || data.handles.end.selected)) {
|
||||||
|
lineColor = activeColor;
|
||||||
|
}
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.strokeStyle = color;
|
context.strokeStyle = lineColor || color;
|
||||||
context.lineWidth = strokeWidth;
|
context.lineWidth = strokeWidth;
|
||||||
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
|
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
|
||||||
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
|
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
|
||||||
context.stroke();
|
context.stroke();
|
||||||
|
|
||||||
// Draw perpendicular line
|
// Draw perpendicular line
|
||||||
drawPerpendicularLine(context, eventData, element, data, color, strokeWidth);
|
let perpendicularColor;
|
||||||
|
if (!data.active && (data.handles.perpendicularStart.selected || data.handles.perpendicularEnd.selected)) {
|
||||||
|
perpendicularColor = activeColor;
|
||||||
|
}
|
||||||
|
drawPerpendicularLine(context, eventData, element, data, perpendicularColor || color, strokeWidth);
|
||||||
|
|
||||||
// Draw the handles
|
// Draw the handles
|
||||||
drawHandles(context, eventData, data.handles, color, { drawHandlesIfActive: true });
|
const handlesColor = lineColor || perpendicularColor || color;
|
||||||
|
drawHandles(context, eventData, data.handles, handlesColor, { drawHandlesIfActive: true });
|
||||||
|
|
||||||
// Calculate the long axis length
|
// Calculate the long axis length
|
||||||
var dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
|
var dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user