@ohif/app 3.13.0-beta.65 → 3.13.0-beta.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{2851.bundle.ffc5656f20a4159d591d.js → 2851.bundle.daa0f5f8bca6492d7033.js} +86 -12
  2. package/dist/{5485.bundle.c59e61ecef95882924d1.js → 5485.bundle.2149d00e98cfcecb114b.js} +10 -4
  3. package/dist/{7166.bundle.bd50b3917b5ee6166971.js → 7166.bundle.04b935471132c7d203f2.js} +160 -25
  4. package/dist/{9927.bundle.21cdba4cf5309feb8b7d.js → 9927.bundle.e4186f993674729cef10.js} +4 -0
  5. package/dist/app.bundle.css +1 -1
  6. package/dist/{app.bundle.9e45525b479dad4d8113.js → app.bundle.f03d71919b8eff3b1f22.js} +57 -4
  7. package/dist/index.html +1 -1
  8. package/dist/sw.js +1 -1
  9. package/package.json +20 -20
  10. /package/dist/{1459.bundle.b76252d4cbc3588eba65.js → 1459.bundle.a159e0dd401123bf9e48.js} +0 -0
  11. /package/dist/{1933.bundle.10e823bd588169da5894.js → 1933.bundle.110d30b6901499a2103d.js} +0 -0
  12. /package/dist/{2018.bundle.a2960b28da742a90207e.js → 2018.bundle.55568a2358323282a1d8.js} +0 -0
  13. /package/dist/{213.bundle.33ca5d29734d9e99a676.js → 213.bundle.364a8317839173e8ea12.js} +0 -0
  14. /package/dist/{2424.bundle.31d8e6bdf23d51886680.js → 2424.bundle.ad9d0bbeb7723bf434dd.js} +0 -0
  15. /package/dist/{3138.bundle.2fd53c9e63b1aea321ac.js → 3138.bundle.1b2ed03742a5cf16d22b.js} +0 -0
  16. /package/dist/{3461.bundle.b50d8125ecc168f22da3.js → 3461.bundle.f499a235aa460895003e.js} +0 -0
  17. /package/dist/{4507.bundle.061dfcf4609ef7aa8ede.js → 4507.bundle.2534b564fe3f0ce90801.js} +0 -0
  18. /package/dist/{4819.bundle.ac518de1987ad93304c8.js → 4819.bundle.11a2ec62c5d49262edf1.js} +0 -0
  19. /package/dist/{5015.bundle.46f8b754a318286c18ad.js → 5015.bundle.6dc4e690443e7d5215f6.js} +0 -0
  20. /package/dist/{5028.bundle.608de6dde0d0af9e2b3e.js → 5028.bundle.723ddddb2203c1c0d2e7.js} +0 -0
  21. /package/dist/{5457.bundle.449b35dfd1134c977985.js → 5457.bundle.180ec36f95f7dfbdb63c.js} +0 -0
  22. /package/dist/{6027.bundle.ea6f6e5bbb336cdb2796.js → 6027.bundle.ad09ef0a6ab5ab0100ad.js} +0 -0
  23. /package/dist/{7639.bundle.04596df767fc6b0003a3.js → 7639.bundle.29a1a0e1df7929296a3e.js} +0 -0
  24. /package/dist/{8305.bundle.a9764cd29cfa5bc6fd79.js → 8305.bundle.63b6a800160f4da7c372.js} +0 -0
  25. /package/dist/{8499.bundle.4a7f127900cf03af4e49.js → 8499.bundle.b9cee1e292a04237794a.js} +0 -0
  26. /package/dist/{85.bundle.e122f01517ddea1e3af0.js → 85.bundle.856bfa0f56bba25ff5fb.js} +0 -0
  27. /package/dist/{8558.bundle.522dbc153f443298deaa.js → 8558.bundle.685196a726b715d41ff0.js} +0 -0
  28. /package/dist/{8583.bundle.bd1d92122c5ebfb867fc.js → 8583.bundle.a7afd7affafa244e55e7.js} +0 -0
@@ -2779,14 +2779,12 @@ function resolveConfigFetchPolicy(rawUrl, policy = {}) {
2779
2779
  }
2780
2780
  async function fetchConfigJson(normalizedPolicy) {
2781
2781
  const {
2782
- normalizedUrl,
2783
- isAuthenticated,
2784
- isSameOrigin
2782
+ normalizedUrl
2785
2783
  } = normalizedPolicy;
2786
- const response = isAuthenticated || isSameOrigin ? await fetch(normalizedUrl) : await fetch(normalizedUrl, {
2784
+ const response = await fetch(normalizedUrl, {
2787
2785
  method: 'GET',
2788
2786
  mode: 'cors',
2789
- credentials: 'omit',
2787
+ credentials: 'same-origin',
2790
2788
  redirect: 'error',
2791
2789
  referrerPolicy: 'no-referrer'
2792
2790
  });
@@ -10614,8 +10612,8 @@ function AboutModalDefault() {
10614
10612
  name
10615
10613
  } = (0,browser_detect_es5/* default */.A)();
10616
10614
  const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
10617
- const versionNumber = "3.13.0-beta.65";
10618
- const commitHash = "62620afb9b7d8d0302584f125704509d65ae6a2d";
10615
+ const versionNumber = "3.13.0-beta.67";
10616
+ const commitHash = "691e26731f4f3b3957fe81fc051b09c972696cf6";
10619
10617
  const [main, beta] = versionNumber.split('-');
10620
10618
  return /*#__PURE__*/react.createElement(ui_next_src/* AboutModal */.VTU, {
10621
10619
  className: "w-[400px]"
@@ -10646,16 +10644,49 @@ const {
10646
10644
  defaultLanguage,
10647
10645
  currentLanguage: currentLanguageFn
10648
10646
  } = i18n_src/* default */.A;
10647
+ const MODIFIER_OPTIONS = [{
10648
+ value: '16',
10649
+ label: 'Shift'
10650
+ }, {
10651
+ value: '17',
10652
+ label: 'Ctrl'
10653
+ }, {
10654
+ value: '18',
10655
+ label: 'Alt'
10656
+ }, {
10657
+ value: '91',
10658
+ label: 'Meta'
10659
+ }];
10660
+ const DEFAULT_TOOL_BINDINGS_STORAGE_KEY = 'user-preferred-tool-bindings';
10661
+ function getToolBindingsStorageKey(customizationService) {
10662
+ const customizationValue = customizationService?.getCustomization('ohif.userPreferences.toolBindingsStorageKey');
10663
+ return typeof customizationValue === 'string' && customizationValue.length > 0 ? customizationValue : DEFAULT_TOOL_BINDINGS_STORAGE_KEY;
10664
+ }
10665
+ function getToolModifier(toolGroupService, toolGroupId, toolName) {
10666
+ if (!toolGroupService) {
10667
+ return null;
10668
+ }
10669
+ const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
10670
+ if (!bindings?.length) {
10671
+ return null;
10672
+ }
10673
+ const modifierBinding = bindings.find(binding => binding.modifierKey != null && binding.numTouchPoints == null);
10674
+ return modifierBinding?.modifierKey != null ? String(modifierBinding.modifierKey) : null;
10675
+ }
10649
10676
  function UserPreferencesModalDefault({
10650
10677
  hide
10651
10678
  }) {
10652
10679
  const {
10653
- hotkeysManager
10680
+ hotkeysManager,
10681
+ servicesManager
10654
10682
  } = (0,src/* useSystem */.Jg)();
10655
10683
  const {
10656
10684
  t,
10657
10685
  i18n: i18nextInstance
10658
10686
  } = (0,es/* useTranslation */.Bd)('UserPreferencesModal');
10687
+ const toolGroupService = servicesManager?.services?.toolGroupService;
10688
+ const customizationService = servicesManager?.services?.customizationService;
10689
+ const toolBindingsStorageKey = getToolBindingsStorageKey(customizationService);
10659
10690
  const {
10660
10691
  hotkeyDefinitions = {},
10661
10692
  hotkeyDefaults = {}
@@ -10672,9 +10703,11 @@ function UserPreferencesModalDefault({
10672
10703
  const resolvedHotkeyDefaults = Object.keys(hotkeyDefaults).length ? hotkeyDefaults : fallbackHotkeyDefinitions;
10673
10704
  const initialHotkeyDefinitions = Object.keys(hotkeyDefinitions).length ? hotkeyDefinitions : resolvedHotkeyDefaults;
10674
10705
  const currentLanguage = currentLanguageFn();
10706
+ const initialCrosshairModifier = (0,react.useMemo)(() => getToolModifier(toolGroupService, 'mpr', 'Crosshairs'), [toolGroupService]);
10675
10707
  const [state, setState] = (0,react.useState)({
10676
10708
  hotkeyDefinitions: initialHotkeyDefinitions,
10677
- languageValue: currentLanguage.value
10709
+ languageValue: currentLanguage.value,
10710
+ crosshairModifier: initialCrosshairModifier
10678
10711
  });
10679
10712
  const onLanguageChangeHandler = value => {
10680
10713
  setState(state => ({
@@ -10698,9 +10731,11 @@ function UserPreferencesModalDefault({
10698
10731
  setState(state => ({
10699
10732
  ...state,
10700
10733
  languageValue: defaultLanguage.value,
10701
- hotkeyDefinitions: resolvedHotkeyDefaults
10734
+ hotkeyDefinitions: resolvedHotkeyDefaults,
10735
+ crosshairModifier: initialCrosshairModifier
10702
10736
  }));
10703
10737
  hotkeysManager.restoreDefaultBindings();
10738
+ localStorage.removeItem(toolBindingsStorageKey);
10704
10739
  };
10705
10740
  const displayNames = react.useMemo(() => {
10706
10741
  if (typeof Intl === 'undefined' || typeof Intl.DisplayNames !== 'function') {
@@ -10757,7 +10792,32 @@ function UserPreferencesModalDefault({
10757
10792
  onChange: newKeys => onHotkeyChangeHandler(id, newKeys),
10758
10793
  placeholder: definition.keys,
10759
10794
  hotkeys: src/* hotkeys */.ot
10760
- })))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Left, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Auxiliary, {
10795
+ }))), state.crosshairModifier != null && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* UserPreferencesModal */.xMy.SubHeading, null, t('ModifierKeys', {
10796
+ defaultValue: 'Modifier Keys'
10797
+ })), /*#__PURE__*/react.createElement(ui_next_src/* UserPreferencesModal */.xMy.HotkeysGrid, null, /*#__PURE__*/react.createElement("div", {
10798
+ className: "flex items-center justify-between gap-2"
10799
+ }, /*#__PURE__*/react.createElement("span", {
10800
+ className: "text-foreground text-base"
10801
+ }, t('CrosshairsModifier', {
10802
+ defaultValue: 'Crosshairs'
10803
+ })), /*#__PURE__*/react.createElement("div", {
10804
+ className: "flex items-center gap-1.5"
10805
+ }, /*#__PURE__*/react.createElement("span", {
10806
+ className: "text-muted-foreground text-sm"
10807
+ }, t('PlusLeftClick', {
10808
+ defaultValue: 'Left Click +'
10809
+ })), /*#__PURE__*/react.createElement(ui_next_src/* Select */.l6P, {
10810
+ value: state.crosshairModifier,
10811
+ onValueChange: val => setState(s => ({
10812
+ ...s,
10813
+ crosshairModifier: val
10814
+ }))
10815
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
10816
+ className: "w-16"
10817
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, null)), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, MODIFIER_OPTIONS.map(opt => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
10818
+ key: opt.value,
10819
+ value: opt.value
10820
+ }, opt.label))))))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Left, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Auxiliary, {
10761
10821
  onClick: onResetHandler
10762
10822
  }, t('Reset to defaults'))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
10763
10823
  onClick: () => {
@@ -10774,6 +10834,19 @@ function UserPreferencesModalDefault({
10774
10834
  return; // Exit early since we're reloading
10775
10835
  }
10776
10836
  hotkeysManager.setHotkeys(state.hotkeyDefinitions);
10837
+ if (toolGroupService && state.crosshairModifier != null) {
10838
+ const bindings = [{
10839
+ mouseButton: 1,
10840
+ modifierKey: Number(state.crosshairModifier)
10841
+ }];
10842
+ toolGroupService.setToolBindings('mpr', 'Crosshairs', bindings);
10843
+ toolGroupService.applyToolBindings('mpr', 'Crosshairs');
10844
+ localStorage.setItem(toolBindingsStorageKey, JSON.stringify({
10845
+ mpr: {
10846
+ Crosshairs: bindings
10847
+ }
10848
+ }));
10849
+ }
10777
10850
  src/* hotkeys */.ot.stopRecord();
10778
10851
  src/* hotkeys */.ot.unpause();
10779
10852
  hide();
@@ -10781,7 +10854,8 @@ function UserPreferencesModalDefault({
10781
10854
  }, t('Save')))));
10782
10855
  }
10783
10856
  /* harmony default export */ const userPreferencesCustomization = ({
10784
- 'ohif.userPreferencesModal': UserPreferencesModalDefault
10857
+ 'ohif.userPreferencesModal': UserPreferencesModalDefault,
10858
+ 'ohif.userPreferences.toolBindingsStorageKey': DEFAULT_TOOL_BINDINGS_STORAGE_KEY
10785
10859
  });
10786
10860
  ;// ../../../extensions/default/src/customizations/reportDialogCustomization.tsx
10787
10861
 
@@ -295,6 +295,10 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
295
295
  }],
296
296
  disabled: [{
297
297
  toolName: toolNames.Crosshairs,
298
+ bindings: [{
299
+ mouseButton: Enums.MouseBindings.Primary,
300
+ modifierKey: Enums.KeyboardBindings.Shift
301
+ }],
298
302
  configuration: {
299
303
  viewportIndicators: true,
300
304
  viewportIndicatorsConfig: {
@@ -302,7 +306,6 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
302
306
  xOffset: 0.95,
303
307
  yOffset: 0.05
304
308
  },
305
- disableOnPassive: true,
306
309
  autoPan: {
307
310
  enabled: false,
308
311
  panSize: 10
@@ -921,15 +924,18 @@ const toolbarButtons = [
921
924
  type: 'tool',
922
925
  icon: 'tool-crosshair',
923
926
  label: i18next/* default */.A.t('Buttons:Crosshairs'),
927
+ tooltip: i18next/* default */.A.t('Buttons:Click to toggle on or off'),
924
928
  commands: {
925
- commandName: 'setToolActiveToolbar',
929
+ commandName: 'toggleActiveDisabledToolbar',
926
930
  commandOptions: {
927
931
  toolGroupIds: ['mpr']
928
932
  }
929
933
  },
930
934
  evaluate: {
931
- name: 'evaluate.cornerstoneTool',
932
- disabledText: i18next/* default */.A.t('Buttons:Select an MPR viewport to enable this tool')
935
+ name: 'evaluate.cornerstoneTool.toggleWithModifier',
936
+ disabledText: i18next/* default */.A.t('Buttons:Select an MPR viewport to enable this tool'),
937
+ toggledOnIcon: 'tool-crosshair-checked',
938
+ defaultIcon: 'tool-crosshair'
933
939
  }
934
940
  }
935
941
  }, {
@@ -10577,7 +10577,14 @@ function commandsModule({
10577
10577
  }
10578
10578
  function _getActiveViewportToolGroupId() {
10579
10579
  const viewport = _getActiveViewportEnabledElement();
10580
- return toolGroupService.getToolGroupForViewport(viewport.id);
10580
+ const toolGroup = viewport && toolGroupService.getToolGroupForViewport(viewport.id);
10581
+ return toolGroup?.id;
10582
+ }
10583
+ function _usesPrimaryActivation(bindings) {
10584
+ if (!bindings?.length) {
10585
+ return true;
10586
+ }
10587
+ return bindings.some(binding => binding.mouseButton === dist_esm.Enums.MouseBindings.Primary && binding.modifierKey == null && binding.numTouchPoints == null);
10581
10588
  }
10582
10589
  function _getActiveSegmentationInfo() {
10583
10590
  const viewportId = viewportGridService.getActiveViewportId();
@@ -11444,31 +11451,46 @@ function commandsModule({
11444
11451
  toggleActiveDisabledToolbar({
11445
11452
  value,
11446
11453
  itemId,
11447
- toolGroupId
11454
+ toolGroupId,
11455
+ toolGroupIds
11448
11456
  }) {
11449
11457
  const toolName = itemId || value;
11450
- toolGroupId = toolGroupId ?? _getActiveViewportToolGroupId();
11451
- const toolGroup = toolGroupService.getToolGroup(toolGroupId);
11452
- if (!toolGroup || !toolGroup.hasTool(toolName)) {
11453
- return;
11454
- }
11455
- const toolIsActive = [dist_esm.Enums.ToolModes.Active, dist_esm.Enums.ToolModes.Enabled, dist_esm.Enums.ToolModes.Passive].includes(toolGroup.getToolOptions(toolName).mode);
11456
- toolIsActive ? toolGroup.setToolDisabled(toolName) : actions.setToolActive({
11457
- toolName,
11458
- toolGroupId
11459
- });
11460
-
11461
- // we should set the previously active tool to active after we set the
11462
- // current tool disabled
11463
- if (toolIsActive) {
11464
- const prevToolName = toolGroup.getPrevActivePrimaryToolName();
11465
- if (prevToolName !== toolName) {
11458
+ const resolvedToolGroupIds = toolGroupIds?.length ? toolGroupIds : [toolGroupId ?? _getActiveViewportToolGroupId()];
11459
+ resolvedToolGroupIds.forEach(toolGroupId => {
11460
+ const toolGroup = toolGroupService.getToolGroup(toolGroupId);
11461
+ if (!toolGroup || !toolGroup.hasTool(toolName)) {
11462
+ return;
11463
+ }
11464
+ const toolIsActive = [dist_esm.Enums.ToolModes.Active, dist_esm.Enums.ToolModes.Enabled, dist_esm.Enums.ToolModes.Passive].includes(toolGroup.getToolOptions(toolName).mode);
11465
+ if (toolIsActive) {
11466
+ toolGroup.setToolDisabled(toolName);
11467
+ const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
11468
+ if (_usesPrimaryActivation(bindings)) {
11469
+ // we should set the previously active tool to active after we set the
11470
+ // current tool disabled
11471
+ const prevToolName = toolGroup.getPrevActivePrimaryToolName();
11472
+ if (prevToolName !== toolName) {
11473
+ actions.setToolActive({
11474
+ toolName: prevToolName,
11475
+ toolGroupId
11476
+ });
11477
+ }
11478
+ }
11479
+ return;
11480
+ }
11481
+ const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
11482
+ if (_usesPrimaryActivation(bindings)) {
11466
11483
  actions.setToolActive({
11467
- toolName: prevToolName,
11468
- toolGroupId
11484
+ toolName,
11485
+ toolGroupId,
11486
+ bindings
11487
+ });
11488
+ } else {
11489
+ toolGroup.setToolActive(toolName, {
11490
+ bindings
11469
11491
  });
11470
11492
  }
11471
- }
11493
+ });
11472
11494
  },
11473
11495
  setToolActiveToolbar: ({
11474
11496
  value,
@@ -18475,6 +18497,36 @@ function getToolbarModule({
18475
18497
  isActive: isPrimaryActive
18476
18498
  };
18477
18499
  }
18500
+ }, {
18501
+ name: 'evaluate.cornerstoneTool.toggleWithModifier',
18502
+ evaluate: ({
18503
+ viewportId,
18504
+ button,
18505
+ disabledText,
18506
+ toggledOnIcon,
18507
+ defaultIcon
18508
+ }) => {
18509
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
18510
+ if (!toolGroup) {
18511
+ return;
18512
+ }
18513
+ const toolName = toolbarService.getToolNameForButton(button);
18514
+ if (!toolGroup.hasTool(toolName)) {
18515
+ return getDisabledState(disabledText);
18516
+ }
18517
+ const {
18518
+ mode
18519
+ } = toolGroup.getToolOptions(toolName) ?? {};
18520
+ const isToggled = mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Enabled;
18521
+ const toolBindings = toolGroupService.getToolBindings(toolGroup.id, toolName);
18522
+ const hasModifierKey = toolBindings?.some(binding => binding.modifierKey != null) ?? false;
18523
+ return {
18524
+ disabled: false,
18525
+ isActive: false,
18526
+ isToggled,
18527
+ icon: isToggled && hasModifierKey && toggledOnIcon ? toggledOnIcon : defaultIcon ?? button.props.icon
18528
+ };
18529
+ }
18478
18530
  }, {
18479
18531
  name: 'evaluate.action',
18480
18532
  evaluate: () => {
@@ -18627,7 +18679,9 @@ class ToolGroupService {
18627
18679
  this.cornerstoneViewportService = void 0;
18628
18680
  this.viewportGridService = void 0;
18629
18681
  this.uiNotificationService = void 0;
18682
+ this.customizationService = void 0;
18630
18683
  this.toolGroupIds = new Set();
18684
+ this.toolBindingsMap = new Map();
18631
18685
  /**
18632
18686
  * Service-specific
18633
18687
  */
@@ -18653,11 +18707,13 @@ class ToolGroupService {
18653
18707
  const {
18654
18708
  cornerstoneViewportService,
18655
18709
  viewportGridService,
18656
- uiNotificationService
18710
+ uiNotificationService,
18711
+ customizationService
18657
18712
  } = servicesManager.services;
18658
18713
  this.cornerstoneViewportService = cornerstoneViewportService;
18659
18714
  this.viewportGridService = viewportGridService;
18660
18715
  this.uiNotificationService = uiNotificationService;
18716
+ this.customizationService = customizationService;
18661
18717
  this.listeners = {};
18662
18718
  this.EVENTS = ToolGroupService_EVENTS;
18663
18719
  Object.assign(this, src/* pubSubServiceInterface */.Ml);
@@ -18715,6 +18771,7 @@ class ToolGroupService {
18715
18771
  destroy() {
18716
18772
  dist_esm.ToolGroupManager.destroy();
18717
18773
  this.toolGroupIds = new Set();
18774
+ this.toolBindingsMap.clear();
18718
18775
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.TOOL_ACTIVATED, this._onToolActivated);
18719
18776
  }
18720
18777
  destroyToolGroup(toolGroupId) {
@@ -18769,6 +18826,7 @@ class ToolGroupService {
18769
18826
  // this.changeConfigurationIfNecessary(toolGroup, volumeId);
18770
18827
  this._addTools(toolGroup, tools, configs);
18771
18828
  this._setToolsMode(toolGroup, tools);
18829
+ this._loadPersistedBindings(toolGroupId);
18772
18830
  }
18773
18831
  createToolGroupAndAddTools(toolGroupId, tools) {
18774
18832
  const toolGroup = this.createToolGroup(toolGroupId);
@@ -18808,6 +18866,46 @@ class ToolGroupService {
18808
18866
  getActivePrimaryMouseButtonTool(toolGroupId) {
18809
18867
  return this.getToolGroup(toolGroupId)?.getActivePrimaryMouseButtonTool();
18810
18868
  }
18869
+ getToolBindings(toolGroupId, toolName) {
18870
+ return this.toolBindingsMap.get(toolGroupId)?.get(toolName);
18871
+ }
18872
+ setToolBindings(toolGroupId, toolName, bindings) {
18873
+ if (!this.toolBindingsMap.has(toolGroupId)) {
18874
+ this.toolBindingsMap.set(toolGroupId, new Map());
18875
+ }
18876
+ this.toolBindingsMap.get(toolGroupId).set(toolName, bindings);
18877
+ }
18878
+ applyToolBindings(toolGroupId, toolName) {
18879
+ const toolGroup = dist_esm.ToolGroupManager.getToolGroup(toolGroupId);
18880
+ if (!toolGroup || !toolGroup.hasTool(toolName)) {
18881
+ return;
18882
+ }
18883
+ const bindings = this.getToolBindings(toolGroupId, toolName);
18884
+ if (!bindings) {
18885
+ return;
18886
+ }
18887
+ const {
18888
+ mode
18889
+ } = toolGroup.getToolOptions(toolName);
18890
+ if (mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Enabled) {
18891
+ toolGroup.setToolActive(toolName, {
18892
+ bindings
18893
+ });
18894
+ }
18895
+ }
18896
+ getAllToolBindings() {
18897
+ const result = [];
18898
+ for (const [toolGroupId, toolMap] of this.toolBindingsMap) {
18899
+ for (const [toolName, bindings] of toolMap) {
18900
+ result.push({
18901
+ toolGroupId,
18902
+ toolName,
18903
+ bindings
18904
+ });
18905
+ }
18906
+ }
18907
+ return result;
18908
+ }
18811
18909
  _setToolsMode(toolGroup, tools) {
18812
18910
  const {
18813
18911
  active,
@@ -18820,6 +18918,9 @@ class ToolGroupService {
18820
18918
  toolName,
18821
18919
  bindings
18822
18920
  }) => {
18921
+ if (bindings) {
18922
+ this.setToolBindings(toolGroup.id, toolName, bindings);
18923
+ }
18823
18924
  toolGroup.setToolActive(toolName, {
18824
18925
  bindings
18825
18926
  });
@@ -18827,22 +18928,34 @@ class ToolGroupService {
18827
18928
  }
18828
18929
  if (passive) {
18829
18930
  passive.forEach(({
18830
- toolName
18931
+ toolName,
18932
+ bindings
18831
18933
  }) => {
18934
+ if (bindings) {
18935
+ this.setToolBindings(toolGroup.id, toolName, bindings);
18936
+ }
18832
18937
  toolGroup.setToolPassive(toolName);
18833
18938
  });
18834
18939
  }
18835
18940
  if (enabled) {
18836
18941
  enabled.forEach(({
18837
- toolName
18942
+ toolName,
18943
+ bindings
18838
18944
  }) => {
18945
+ if (bindings) {
18946
+ this.setToolBindings(toolGroup.id, toolName, bindings);
18947
+ }
18839
18948
  toolGroup.setToolEnabled(toolName);
18840
18949
  });
18841
18950
  }
18842
18951
  if (disabled) {
18843
18952
  disabled.forEach(({
18844
- toolName
18953
+ toolName,
18954
+ bindings
18845
18955
  }) => {
18956
+ if (bindings) {
18957
+ this.setToolBindings(toolGroup.id, toolName, bindings);
18958
+ }
18846
18959
  toolGroup.setToolDisabled(toolName);
18847
18960
  });
18848
18961
  }
@@ -18878,6 +18991,28 @@ class ToolGroupService {
18878
18991
  addTools(tools.disabled);
18879
18992
  }
18880
18993
  }
18994
+ _loadPersistedBindings(toolGroupId) {
18995
+ try {
18996
+ const stored = localStorage.getItem(this._getToolBindingsStorageKey());
18997
+ if (!stored) {
18998
+ return;
18999
+ }
19000
+ const parsed = JSON.parse(stored);
19001
+ const toolGroupBindings = parsed[toolGroupId];
19002
+ if (!toolGroupBindings) {
19003
+ return;
19004
+ }
19005
+ for (const [toolName, bindings] of Object.entries(toolGroupBindings)) {
19006
+ this.setToolBindings(toolGroupId, toolName, bindings);
19007
+ }
19008
+ } catch {
19009
+ // ignore corrupt localStorage
19010
+ }
19011
+ }
19012
+ _getToolBindingsStorageKey() {
19013
+ const customizationValue = this.customizationService?.getCustomization('ohif.userPreferences.toolBindingsStorageKey');
19014
+ return typeof customizationValue === 'string' && customizationValue.length > 0 ? customizationValue : 'user-preferred-tool-bindings';
19015
+ }
18881
19016
  }
18882
19017
  _ToolGroupService = ToolGroupService;
18883
19018
  ToolGroupService.REGISTRATION = {
@@ -157,6 +157,10 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) {
157
157
  enabled: [],
158
158
  disabled: [{
159
159
  toolName: toolNames.Crosshairs,
160
+ bindings: [{
161
+ mouseButton: Enums.MouseBindings.Primary,
162
+ modifierKey: Enums.KeyboardBindings.Shift
163
+ }],
160
164
  configuration: {
161
165
  disableOnPassive: true,
162
166
  autoPan: {