cornerstonejs / cornerstoneTools

[Deprecated] Use Cornerstone3D Instead https://cornerstonejs.org/
MIT License
579 stars 456 forks source link

Tools are not reinializing for other tabs [custom plugin built with cornerstone] #1571

Open imran-khani opened 3 months ago

imran-khani commented 3 months ago

Issue: Tools Not Reinitializing for Other Tabs

Description

I'm encountering an issue with Cornerstone tools where they are not reinitializing properly when switching between tabs. I have a setup where multiple DICOM viewers are initialized within tabs, and the tools need to be reinitialized each time a tab is switched. However, it seems that the tools are not being set up correctly for the new active tab, causing the tools to not work as expected.

Steps to Reproduce

  1. Initialize multiple DICOM viewers within tabs.
  2. Switch between the tabs.
  3. Observe that the tools are not reinitialized properly for the newly active tab.

Expected Behavior

The tools should be reinitialized and activated correctly for each tab when it becomes active.

Actual Behavior

The tools are not reinitialized, causing issues with tool activation and functionality in the newly active tab.

Code Example

Here is a simplified version of my code:


document.addEventListener('DOMContentLoaded', function(){
  initializeDICOMViewer();
});

function initializeDICOMViewer(){
  cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
  cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
  cornerstoneWADOImageLoader.webWorkerManager.initialize({
    maxWebWorkers: navigator.hardwareConcurrency || 1,
    startWebWorkersOnDemand: true,
    taskConfiguration: {
      decodeTask: {
        initializeCodecsOnStartup: false,
        usePDFJS: false,
        strict: false
      }
    }
  });

  cornerstoneTools.init({
    globalToolSyncEnabled: true,
  });

  setupViewerContainers();
  setupToolButtons();
}

function setupViewerContainers(){
  const containers = document.querySelectorAll('.dcm-container');
  containers.forEach((container, containerIndex) => {
    initializeContainer(container, container.dataset.instance || containerIndex);
  });
}

function initializeContainer(container, instance){
  const images = dicomImageFiles[instance];
  if (!images || images.length === 0) {
    return;
  }

  const viewersContainer = container.querySelector('.dcm-viewers');
  const viewerElement = document.createElement('div');
  viewerElement.className = 'dcm-viewer';
  viewerElement.style.width = '100%';
  viewerElement.style.height = '500px';
  viewerElement.setAttribute('data-active-tool', 'Wwwc');
  viewersContainer.appendChild(viewerElement);

  cornerstone.enable(viewerElement);

  viewers.push({
    element: viewerElement,
    containerIndex: instance,
    instance: instance,
    images: images,
    currentImageIndex: 0,
    loaded: false
  });

  setupTools(viewerElement);
  loadImage(viewers[viewers.length - 1]); // Load the first image immediately
}

function setupTools(element){
  const tools = [
    { toolName: 'PanTool', options: {} },
    {
      toolName: 'ZoomTool',
      options: { configuration: { invert: false, preventHandleOutsideImage: false, minScale: 0.1, maxScale: 20.0 } }
    },
    { toolName: 'WwwcTool', options: {} },
    { toolName: 'LengthTool', options: {} },
    { toolName: 'ProbeTool', options: {} },
    { toolName: 'AngleTool', options: {} },
    { toolName: 'EllipticalRoiTool', options: {} },
    { toolName: 'RectangleRoiTool', options: {} },
    { toolName: 'RotateTool', options: {} }
  ];

  tools.forEach(({ toolName, options }) => {
    cornerstoneTools.addTool(cornerstoneTools[toolName], options);
  });

  cornerstoneTools.setToolActiveForElement(element, 'WwwcTool', { mouseButtonMask: 1 });
  cornerstoneTools.setToolActiveForElement(element, 'ZoomTool', { mouseButtonMask: 2 });
}

function loadImage(viewer){
  const imageId = `wadouri:${viewer.images[viewer.currentImageIndex]}`;
  cornerstone.loadAndCacheImage(imageId).then(image => {
    cornerstone.displayImage(viewer.element, image);
    cornerstone.resize(viewer.element, true);
    cornerstone.fitToWindow(viewer.element);
    viewer.loaded = true;
    if (!viewer.scrollHandlerSet) {
      setupScrollHandler(viewer);
      viewer.scrollHandlerSet = true;
    }
    setupTools(viewer.element); // Ensure tools are re-initialized
  }).catch(error => {
    console.error('Error loading image:', error);
  });
}

function setupScrollHandler(viewer){
  viewer.element.addEventListener('wheel', (event) => {
    event.preventDefault();
    if (event.deltaY > 0) {
      viewer.currentImageIndex = (viewer.currentImageIndex + 1) % viewer.images.length;
    } else {
      viewer.currentImageIndex = (viewer.currentImageIndex - 1 + viewer.images.length) % viewer.images.length;
    }
    loadImage(viewer);
  });
}

function activateTool(tool, container){
  const viewerElement = container.querySelector('.dcm-viewer');
  viewerElement.setAttribute('data-active-tool', tool);
  if (tool === 'Reset') {
    resetImage(viewerElement);
  } else {
    const toolName = tool === 'WindowLevel' ? 'Wwwc' : tool;
    cornerstoneTools.setToolActiveForElement(viewerElement, toolName, { mouseButtonMask: 1 });
  }
}

function handleTabSwitch(){
  const activePanel = document.querySelector('.wonderplugintabs-panel-active');   
  if (activePanel) {
    const container = activePanel.querySelector('.dcm-container');
    if (container) {
      const viewer = viewers.find(v => v.element.closest('.dcm-container') === container);
      if (viewer) {
        loadImage(viewer);
      } else {
        initializeContainer(container, container.dataset.instance);
      }
    }
  }
}

document.querySelectorAll('.wonderplugintabs-header-li').forEach(header => {
  header.addEventListener('click', function(){
    setTimeout(() => {
      handleTabSwitch();
    }, 500);
  });
});