structure-info.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { PluginBehavior } from '../../../behavior/behavior';
  7. import { Structure, Model } from '../../../../mol-model/structure';
  8. import { PluginStateObject } from '../../../../mol-plugin-state/objects';
  9. import { StateSelection, StateObject } from '../../../../mol-state';
  10. export const StructureInfo = PluginBehavior.create({
  11. name: 'structure-info-prop',
  12. category: 'custom-props',
  13. display: { name: 'Structure Info' },
  14. ctor: class extends PluginBehavior.Handler {
  15. private get maxModelIndex() {
  16. let maxIndex = -1;
  17. const cells = this.ctx.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model));
  18. for (const c of cells) {
  19. const index = c.obj?.data && Model.Index.get(c.obj?.data).value;
  20. if (index !== undefined && index > maxIndex) maxIndex = index;
  21. }
  22. return maxIndex;
  23. }
  24. private get maxStructureIndex() {
  25. let maxIndex = -1;
  26. const cells = this.ctx.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure));
  27. for (const c of cells) {
  28. const index = c.obj?.data && Structure.Index.get(c.obj?.data).value;
  29. if (index !== undefined && index > maxIndex) maxIndex = index;
  30. }
  31. return maxIndex;
  32. }
  33. private get asymIdOffset() {
  34. let auth = 0;
  35. let label = 0;
  36. const cells = this.ctx.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model));
  37. for (const c of cells) {
  38. const m = c.obj?.data;
  39. if (m) {
  40. const count = Model.AsymIdCount.get(m);
  41. const offset = Model.AsymIdOffset.get(m).value;
  42. if (count !== undefined && offset !== undefined) {
  43. auth = Math.max(auth, offset.auth + count.auth);
  44. label = Math.max(label, offset.label + count.label);
  45. }
  46. }
  47. }
  48. return { auth, label };
  49. }
  50. private setModelMaxIndex() {
  51. const maxIndex = this.maxModelIndex;
  52. const cells = this.ctx.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model));
  53. for (const c of cells) {
  54. const m = c.obj?.data;
  55. if (m) {
  56. Model.MaxIndex.set(m, { value: maxIndex }, maxIndex);
  57. }
  58. }
  59. }
  60. private handleModel(model: Model, oldModel?: Model) {
  61. if (Model.Index.get(model).value === undefined) {
  62. const oldIndex = oldModel && Model.Index.get(oldModel).value;
  63. const value = oldIndex ?? (this.maxModelIndex + 1);
  64. Model.Index.set(model, { value }, value);
  65. }
  66. if (Model.AsymIdOffset.get(model).value === undefined) {
  67. const oldOffset = oldModel && Model.AsymIdOffset.get(oldModel).value;
  68. const value = oldOffset ?? { ...this.asymIdOffset };
  69. Model.AsymIdOffset.set(model, { value }, value);
  70. }
  71. }
  72. private handleStructure(structure: Structure, oldStructure?: Structure) {
  73. if (structure.parent !== undefined) return;
  74. if (Structure.Index.get(structure).value !== undefined) return;
  75. const oldIndex = oldStructure && Structure.Index.get(oldStructure).value;
  76. const value = oldIndex ?? (this.maxStructureIndex + 1);
  77. Structure.Index.set(structure, { value }, value);
  78. }
  79. private handle(ref: string, obj: StateObject<any, StateObject.Type<any>>, oldObj?: StateObject<any, StateObject.Type<any>>) {
  80. if (PluginStateObject.Molecule.Structure.is(obj)) {
  81. const transform = this.ctx.state.data.tree.transforms.get(ref);
  82. if (!transform.transformer.definition.isDecorator && obj.data.parent === undefined) {
  83. this.handleStructure(obj.data, oldObj?.data);
  84. }
  85. } else if (PluginStateObject.Molecule.Model.is(obj)) {
  86. const transform = this.ctx.state.data.tree.transforms.get(ref);
  87. if (!transform.transformer.definition.isDecorator) {
  88. this.handleModel(obj.data, oldObj?.data);
  89. }
  90. }
  91. }
  92. register(): void {
  93. this.ctx.customModelProperties.register(Model.AsymIdOffset, true);
  94. this.ctx.customModelProperties.register(Model.Index, true);
  95. this.ctx.customModelProperties.register(Model.MaxIndex, true);
  96. this.ctx.customStructureProperties.register(Structure.Index, true);
  97. this.subscribeObservable(this.ctx.state.data.events.object.created, o => {
  98. this.handle(o.ref, o.obj);
  99. this.setModelMaxIndex();
  100. });
  101. this.subscribeObservable(this.ctx.state.data.events.object.updated, o => {
  102. this.handle(o.ref, o.obj, o.oldObj);
  103. });
  104. }
  105. unregister() {
  106. this.ctx.customModelProperties.unregister(Model.AsymIdOffset.descriptor.name);
  107. this.ctx.customModelProperties.unregister(Model.Index.descriptor.name);
  108. this.ctx.customModelProperties.unregister(Model.MaxIndex.descriptor.name);
  109. this.ctx.customStructureProperties.unregister(Structure.Index.descriptor.name);
  110. }
  111. }
  112. });