From fb230c2435de677cb3891927fb82eb9d63671697 Mon Sep 17 00:00:00 2001 From: Daniil Sloboda Date: Mon, 5 Aug 2024 13:42:31 +0400 Subject: [PATCH] Preview: Update Image object in KET file to support CDX/CDXML format (#5188) * #5172 - updated ket image format * #5172 - fixed failing types * #5172 - fixed regex * #5172 - fixed package-lock file * #5172 - updated file mime regexp --- package-lock.json | 8 +- .../src/application/editor/actions/erase.ts | 8 +- .../application/editor/actions/fragment.ts | 10 +-- .../src/application/editor/actions/image.ts | 48 ++++++++++++ .../src/application/editor/actions/index.ts | 2 +- .../src/application/editor/actions/paste.ts | 12 +-- .../application/editor/actions/rasterImage.ts | 52 ------------- .../editor/operations/OperationType.ts | 8 +- .../rasterImageMove.ts => image/imageMove.ts} | 10 +-- .../imageResize.ts} | 22 +++--- .../imageUpsertDelete.ts} | 45 +++++------ .../editor/operations/image/index.ts | 3 + .../application/editor/operations/index.ts | 2 +- .../editor/operations/rasterImage/index.ts | 3 - .../application/editor/shared/constants.ts | 4 +- .../render/restruct/generalEnumTypes.ts | 2 +- .../src/application/render/restruct/index.ts | 2 +- .../restruct/{rerasterImage.ts => reImage.ts} | 40 +++++----- .../application/render/restruct/restruct.ts | 18 ++--- .../constants/{rasterImage.ts => image.ts} | 10 +-- .../src/domain/constants/index.ts | 2 +- .../entities/{rasterImage.ts => image.ts} | 78 +++++++++++-------- .../ketcher-core/src/domain/entities/index.ts | 2 +- .../src/domain/entities/struct.ts | 23 +++--- ...asterImageToStruct.ts => imageToStruct.ts} | 6 +- .../domain/serializers/ket/ketSerializer.ts | 14 ++-- .../src/domain/serializers/ket/schema.json | 68 +++++++--------- .../{rasterImageToKet.ts => imageToKet.ts} | 15 ++-- .../domain/serializers/ket/toKet/prepare.ts | 2 +- .../components/Icon/utils/iconNameToIcon.ts | 4 +- .../ketcher-react/src/script/editor/Editor.ts | 8 +- .../src/script/editor/shared/closest.ts | 12 +-- .../src/script/editor/tool/eraser.ts | 10 +-- .../src/script/editor/tool/helper/locate.ts | 14 ++-- .../editor/tool/{rasterImage.ts => image.ts} | 42 +++++----- .../src/script/editor/tool/index.ts | 6 +- .../src/script/editor/tool/select.ts | 23 +++--- .../src/script/ui/action/tools.js | 8 +- .../toolbars/LeftToolbar/LeftToolbar.tsx | 4 +- .../script/ui/views/toolbars/toolbar.types.ts | 4 +- packages/ketcher-standalone/package.json | 2 +- 41 files changed, 327 insertions(+), 329 deletions(-) create mode 100644 packages/ketcher-core/src/application/editor/actions/image.ts delete mode 100644 packages/ketcher-core/src/application/editor/actions/rasterImage.ts rename packages/ketcher-core/src/application/editor/operations/{rasterImage/rasterImageMove.ts => image/imageMove.ts} (68%) rename packages/ketcher-core/src/application/editor/operations/{rasterImage/rasterImageResize.ts => image/imageResize.ts} (75%) rename packages/ketcher-core/src/application/editor/operations/{rasterImage/rasterImageUpsertDelete.ts => image/imageUpsertDelete.ts} (54%) create mode 100644 packages/ketcher-core/src/application/editor/operations/image/index.ts delete mode 100644 packages/ketcher-core/src/application/editor/operations/rasterImage/index.ts rename packages/ketcher-core/src/application/render/restruct/{rerasterImage.ts => reImage.ts} (90%) rename packages/ketcher-core/src/domain/constants/{rasterImage.ts => image.ts} (66%) rename packages/ketcher-core/src/domain/entities/{rasterImage.ts => image.ts} (66%) rename packages/ketcher-core/src/domain/serializers/ket/fromKet/{rasterImageToStruct.ts => imageToStruct.ts} (81%) rename packages/ketcher-core/src/domain/serializers/ket/toKet/{rasterImageToKet.ts => imageToKet.ts} (64%) rename packages/ketcher-react/src/script/editor/tool/{rasterImage.ts => image.ts} (84%) diff --git a/package-lock.json b/package-lock.json index 324a43d374..9b93ad976a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15625,9 +15625,9 @@ } }, "node_modules/indigo-ketcher": { - "version": "1.22.0-rc.3", - "resolved": "https://registry.npmjs.org/indigo-ketcher/-/indigo-ketcher-1.22.0-rc.3.tgz", - "integrity": "sha512-JIvC5UG/m7wOk0y/K8soj7A1k/uaOC4IjK14qgM2RnsA1seO3Pt+qR+4WQ1uhqOQjeZEwZcgW4NfgJYp8bdZCw==" + "version": "1.23.0-dev.4", + "resolved": "https://registry.npmjs.org/indigo-ketcher/-/indigo-ketcher-1.23.0-dev.4.tgz", + "integrity": "sha512-yrEzGJRtNvI+oH1dRpDjgenUj2GpVJf1TQeYaDqSn0ZlcYJ2Lyv2YFbKo4TcsqL04TRmnazd0tkI163tI3t6TA==" }, "node_modules/inflight": { "version": "1.0.6", @@ -35268,7 +35268,7 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.17.9", - "indigo-ketcher": "1.22.0-rc.3", + "indigo-ketcher": "1.23.0-dev.4", "ketcher-core": "*" }, "devDependencies": { diff --git a/packages/ketcher-core/src/application/editor/actions/erase.ts b/packages/ketcher-core/src/application/editor/actions/erase.ts index dd81856f15..acbc6c1ee9 100644 --- a/packages/ketcher-core/src/application/editor/actions/erase.ts +++ b/packages/ketcher-core/src/application/editor/actions/erase.ts @@ -18,7 +18,7 @@ import { AtomDelete, BondDelete, CalcImplicitH, - RasterImageDelete, + ImageDelete, RGroupAttachmentPointRemove, RxnArrowDelete, RxnPlusDelete, @@ -40,7 +40,7 @@ import { fromFragmentSplit } from './fragment'; import { fromRGroupAttachmentPointDeletion } from './rgroupAttachmentPoint'; import { ReStruct } from 'application/render'; import { isNumber } from 'lodash'; -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { IMAGE_KEY } from 'domain/constants'; export function fromOneAtomDeletion(restruct, atomId: number) { return fromFragmentDeletion(restruct, { atoms: [atomId] }); @@ -218,8 +218,8 @@ export function fromFragmentDeletion(restruct, rawSelection) { action.addOp(new TextDelete(id)); }); - selection[RASTER_IMAGE_KEY].forEach((id) => { - action.addOp(new RasterImageDelete(id)); + selection[IMAGE_KEY].forEach((id) => { + action.addOp(new ImageDelete(id)); }); const actionToDeleteRGroupAttachmentPoints = new Action(); diff --git a/packages/ketcher-core/src/application/editor/actions/fragment.ts b/packages/ketcher-core/src/application/editor/actions/fragment.ts index f959f97ded..82aa80d82d 100644 --- a/packages/ketcher-core/src/application/editor/actions/fragment.ts +++ b/packages/ketcher-core/src/application/editor/actions/fragment.ts @@ -28,7 +28,7 @@ import { SGroupDataMove, SimpleObjectMove, TextMove, - RasterImageMove, + ImageMove, } from '../operations'; import { Pile, RGroup, Vec2 } from 'domain/entities'; import { fromRGroupFragment, fromUpdateIfThen } from './rgroup'; @@ -36,7 +36,7 @@ import { fromRGroupFragment, fromUpdateIfThen } from './rgroup'; import { Action } from './action'; import { fromAtomsFragmentAttr } from './atom'; import { getRelSGroupsBySelection } from './utils'; -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { IMAGE_KEY } from 'domain/constants'; export function fromMultipleMove(restruct, lists, d: Vec2) { d = new Vec2(d); @@ -129,9 +129,9 @@ export function fromMultipleMove(restruct, lists, d: Vec2) { }); } - if (lists[RASTER_IMAGE_KEY]) { - lists[RASTER_IMAGE_KEY].forEach((rasterImage) => { - action.addOp(new RasterImageMove(rasterImage, d)); + if (lists[IMAGE_KEY]) { + lists[IMAGE_KEY].forEach((image) => { + action.addOp(new ImageMove(image, d)); }); } diff --git a/packages/ketcher-core/src/application/editor/actions/image.ts b/packages/ketcher-core/src/application/editor/actions/image.ts new file mode 100644 index 0000000000..34b4a66ee2 --- /dev/null +++ b/packages/ketcher-core/src/application/editor/actions/image.ts @@ -0,0 +1,48 @@ +import { ReStruct } from 'application/render'; +import { ImageReferencePositionInfo, Vec2 } from 'domain/entities'; +import { + Action, + ImageDelete, + ImageMove, + ImageResize, + ImageUpsert, +} from 'application/editor'; +import { Image } from 'domain/entities/image'; + +export function fromImageCreation( + reStruct: ReStruct, + bitmap: string, + center: Vec2, + halfSize: Vec2, +) { + const action = new Action(); + const image = new Image(bitmap, center, halfSize); + action.addOp(new ImageUpsert(image)); + return action.perform(reStruct); +} + +export function fromImageDeletion(reStruct: ReStruct, id: number) { + const action = new Action(); + action.addOp(new ImageDelete(id)); + return action.perform(reStruct); +} + +export function fromImageMove(reStruct: ReStruct, id: number, offset: Vec2) { + const action = new Action(); + action.addOp(new ImageMove(id, offset)); + return action.perform(reStruct); +} + +export function fromImageResize( + reStruct: ReStruct, + id: number, + position: Vec2, + referencePositionInfo: ImageReferencePositionInfo, +) { + const action = new Action(); + const positionWithOffset = position.add(referencePositionInfo.offset); + action.addOp( + new ImageResize(id, positionWithOffset, referencePositionInfo.name), + ); + return action.perform(reStruct); +} diff --git a/packages/ketcher-core/src/application/editor/actions/index.ts b/packages/ketcher-core/src/application/editor/actions/index.ts index 3d5553f2f2..7ba2d589ab 100644 --- a/packages/ketcher-core/src/application/editor/actions/index.ts +++ b/packages/ketcher-core/src/application/editor/actions/index.ts @@ -8,7 +8,7 @@ export * from './closelyFusing'; export * from './erase'; export * from './fragment'; export * from './paste'; -export * from './rasterImage'; +export * from './image'; export * from './reaction'; export * from './rgroup'; export * from './rgroupAttachmentPoint'; diff --git a/packages/ketcher-core/src/application/editor/actions/paste.ts b/packages/ketcher-core/src/application/editor/actions/paste.ts index d092e61f34..1acd6f9d22 100644 --- a/packages/ketcher-core/src/application/editor/actions/paste.ts +++ b/packages/ketcher-core/src/application/editor/actions/paste.ts @@ -28,7 +28,7 @@ import { FragmentSetProperties, BondAttr, AtomAttr, - RasterImageUpsert, + ImageUpsert, } from '../operations'; import { fromRGroupAttrs, fromUpdateIfThen } from './rgroup'; @@ -37,7 +37,7 @@ import { SGroup, Struct, Vec2 } from 'domain/entities'; import { fromSgroupAddition } from './sgroup'; import { fromRGroupAttachmentPointAddition } from './rgroupAttachmentPoint'; import { MonomerMicromolecule } from 'domain/entities/monomerMicromolecule'; -import { RasterImage } from 'domain/entities/rasterImage'; +import { Image } from 'domain/entities/image'; export function fromPaste( restruct, @@ -190,11 +190,11 @@ export function fromPaste( ); }); - pstruct.rasterImages.forEach((rasterImage: RasterImage) => { - const clonedImage = rasterImage.clone(); + pstruct.images.forEach((image: Image) => { + const clonedImage = image.clone(); clonedImage.addPositionOffset(offset); - action.addOp(new RasterImageUpsert(clonedImage).perform(restruct)); + action.addOp(new ImageUpsert(clonedImage).perform(restruct)); }); pstruct.rgroups.forEach((rg, rgid) => { @@ -247,7 +247,7 @@ function getStructCenter(struct: Struct): Vec2 { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (struct.texts.size > 0) return struct.texts.get(0)!.position; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - if (struct.rasterImages.size > 0) return struct.rasterImages.get(0)!.center(); + if (struct.images.size > 0) return struct.images.get(0)!.center(); return new Vec2(0, 0); } diff --git a/packages/ketcher-core/src/application/editor/actions/rasterImage.ts b/packages/ketcher-core/src/application/editor/actions/rasterImage.ts deleted file mode 100644 index 5d08edcc12..0000000000 --- a/packages/ketcher-core/src/application/editor/actions/rasterImage.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ReStruct } from 'application/render'; -import { RasterImageReferencePositionInfo, Vec2 } from 'domain/entities'; -import { - Action, - RasterImageDelete, - RasterImageMove, - RasterImageResize, - RasterImageUpsert, -} from 'application/editor'; -import { RasterImage } from 'domain/entities/rasterImage'; - -export function fromRasterImageCreation( - reStruct: ReStruct, - bitmap: string, - center: Vec2, - halfSize: Vec2, -) { - const action = new Action(); - const rasterImage = new RasterImage(bitmap, center, halfSize); - action.addOp(new RasterImageUpsert(rasterImage)); - return action.perform(reStruct); -} - -export function fromRasterImageDeletion(reStruct: ReStruct, id: number) { - const action = new Action(); - action.addOp(new RasterImageDelete(id)); - return action.perform(reStruct); -} - -export function fromRasterImageMove( - reStruct: ReStruct, - id: number, - offset: Vec2, -) { - const action = new Action(); - action.addOp(new RasterImageMove(id, offset)); - return action.perform(reStruct); -} - -export function fromRasterImageResize( - reStruct: ReStruct, - id: number, - position: Vec2, - referencePositionInfo: RasterImageReferencePositionInfo, -) { - const action = new Action(); - const positionWithOffset = position.add(referencePositionInfo.offset); - action.addOp( - new RasterImageResize(id, positionWithOffset, referencePositionInfo.name), - ); - return action.perform(reStruct); -} diff --git a/packages/ketcher-core/src/application/editor/operations/OperationType.ts b/packages/ketcher-core/src/application/editor/operations/OperationType.ts index d0926e042e..eb07ad3135 100644 --- a/packages/ketcher-core/src/application/editor/operations/OperationType.ts +++ b/packages/ketcher-core/src/application/editor/operations/OperationType.ts @@ -82,10 +82,10 @@ export const OperationType = Object.freeze({ DRAWING_ENTITY_SELECT: 'Select drawing entity', DRAWING_ENTITY_HOVER: 'Hover drawing entity', SHOW_POLYMER_BOND_INFORMATION: 'Show polymer bond information', - RASTER_IMAGE_UPSERT: 'Upsert raster image', - RASTER_IMAGE_DELETE: 'Delete raster image', - RASTER_IMAGE_MOVE: 'Move raster image', - RASTER_IMAGE_RESIZE: 'Resize raster image', + IMAGE_UPSERT: 'Upsert image', + IMAGE_DELETE: 'Delete image', + IMAGE_MOVE: 'Move image', + IMAGE_RESIZE: 'Resize image', }); export enum OperationPriority { diff --git a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageMove.ts b/packages/ketcher-core/src/application/editor/operations/image/imageMove.ts similarity index 68% rename from packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageMove.ts rename to packages/ketcher-core/src/application/editor/operations/image/imageMove.ts index 9fd28b9a59..19f0b6d641 100644 --- a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageMove.ts +++ b/packages/ketcher-core/src/application/editor/operations/image/imageMove.ts @@ -4,14 +4,14 @@ import { OperationType } from 'application/editor'; import { ReStruct } from 'application/render'; import { Scale } from 'domain/helpers'; -export class RasterImageMove extends BaseOperation { +export class ImageMove extends BaseOperation { constructor(private id: number, private offset: Vec2) { - super(OperationType.RASTER_IMAGE_MOVE); + super(OperationType.IMAGE_MOVE); } execute(reStruct: ReStruct) { - const renderItem = reStruct.rasterImages.get(this.id); - const item = reStruct.molecule.rasterImages.get(this.id); + const renderItem = reStruct.images.get(this.id); + const item = reStruct.molecule.images.get(this.id); if (!item || !renderItem) { return; @@ -26,6 +26,6 @@ export class RasterImageMove extends BaseOperation { } invert(): BaseOperation { - return new RasterImageMove(this.id, this.offset.negated()); + return new ImageMove(this.id, this.offset.negated()); } } diff --git a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageResize.ts b/packages/ketcher-core/src/application/editor/operations/image/imageResize.ts similarity index 75% rename from packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageResize.ts rename to packages/ketcher-core/src/application/editor/operations/image/imageResize.ts index 9b9c15c706..89a46c3336 100644 --- a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageResize.ts +++ b/packages/ketcher-core/src/application/editor/operations/image/imageResize.ts @@ -1,45 +1,45 @@ import { BaseOperation } from 'application/editor/operations/base'; -import { RasterImageReferenceName, Vec2 } from 'domain/entities'; +import { ImageReferenceName, Vec2 } from 'domain/entities'; import { ReStruct } from 'application/render'; import { OperationType } from 'application/editor'; -const moveLeftPositions: Array = [ +const moveLeftPositions: Array = [ 'topLeftPosition', 'leftMiddlePosition', 'bottomLeftPosition', ]; -const moveRightPositions: Array = [ +const moveRightPositions: Array = [ 'topRightPosition', 'rightMiddlePosition', 'bottomRightPosition', ]; -const moveTopPositions: Array = [ +const moveTopPositions: Array = [ 'topLeftPosition', 'topMiddlePosition', 'topRightPosition', ]; -const moveBottomPositions: Array = [ +const moveBottomPositions: Array = [ 'bottomLeftPosition', 'bottomMiddlePosition', 'bottomRightPosition', ]; -export class RasterImageResize extends BaseOperation { +export class ImageResize extends BaseOperation { private previousPosition: Vec2 | null = null; constructor( private id: number, private position: Vec2, - private referencePositionName: RasterImageReferenceName, + private referencePositionName: ImageReferenceName, ) { - super(OperationType.RASTER_IMAGE_RESIZE); + super(OperationType.IMAGE_RESIZE); } execute(reStruct: ReStruct) { - const item = reStruct.molecule.rasterImages.get(this.id); - const renderItem = reStruct.rasterImages.get(this.id); + const item = reStruct.molecule.images.get(this.id); + const renderItem = reStruct.images.get(this.id); if (!item || !renderItem) { return; @@ -69,7 +69,7 @@ export class RasterImageResize extends BaseOperation { } invert(): BaseOperation { - return new RasterImageResize( + return new ImageResize( this.id, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.previousPosition!, diff --git a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageUpsertDelete.ts b/packages/ketcher-core/src/application/editor/operations/image/imageUpsertDelete.ts similarity index 54% rename from packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageUpsertDelete.ts rename to packages/ketcher-core/src/application/editor/operations/image/imageUpsertDelete.ts index 7e89053e7f..522a3e38b8 100644 --- a/packages/ketcher-core/src/application/editor/operations/rasterImage/rasterImageUpsertDelete.ts +++ b/packages/ketcher-core/src/application/editor/operations/image/imageUpsertDelete.ts @@ -17,55 +17,56 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import { BaseOperation } from 'application/editor/operations/base'; import { OperationType } from 'application/editor'; -import { RasterImage } from 'domain/entities/rasterImage'; +import { Image } from 'domain/entities/image'; import { ReStruct } from 'application/render'; -import { ReRasterImage } from 'application/render/restruct/rerasterImage'; +import { ReImage } from 'application/render/restruct/reImage'; +import { IMAGE_KEY } from 'domain/constants'; -export class RasterImageUpsert extends BaseOperation { - constructor(private readonly rasterImage: RasterImage, private id?: number) { - super(OperationType.RASTER_IMAGE_UPSERT); +export class ImageUpsert extends BaseOperation { + constructor(private readonly image: Image, private id?: number) { + super(OperationType.IMAGE_UPSERT); } execute(reStruct: ReStruct) { const struct = reStruct.molecule; - if (!this.id) { - this.id = struct.rasterImages.newId(); + if (this.id === undefined) { + this.id = struct.images.newId(); } const id = this.id; - const item = this.rasterImage.clone(); - struct.rasterImages.set(id, item); - reStruct.rasterImages.set(id, new ReRasterImage(item)); + const item = this.image.clone(); + struct.images.set(id, item); + reStruct.images.set(id, new ReImage(item)); - BaseOperation.invalidateItem(reStruct, 'rasterImages', id, 1); + BaseOperation.invalidateItem(reStruct, IMAGE_KEY, id, 1); } invert(): BaseOperation { - return new RasterImageDelete(this.id!); + return new ImageDelete(this.id!); } } -export class RasterImageDelete extends BaseOperation { - private rasterImage?: RasterImage; +export class ImageDelete extends BaseOperation { + private image?: Image; constructor(private id: number) { - super(OperationType.RASTER_IMAGE_DELETE); + super(OperationType.IMAGE_DELETE); } execute(reStruct: ReStruct) { - const reRasterImage = reStruct.rasterImages.get(this.id); + const reImage = reStruct.images.get(this.id); - if (!reRasterImage) { + if (!reImage) { return; } - this.rasterImage = reRasterImage.rasterImage.clone(); - reStruct.clearVisel(reRasterImage.visel); + this.image = reImage.image.clone(); + reStruct.clearVisel(reImage.visel); reStruct.markItemRemoved(); - reStruct.rasterImages.delete(this.id); - reStruct.molecule.rasterImages.delete(this.id); + reStruct.images.delete(this.id); + reStruct.molecule.images.delete(this.id); } invert(): BaseOperation { - return new RasterImageUpsert(this.rasterImage!, this.id); + return new ImageUpsert(this.image!, this.id); } } diff --git a/packages/ketcher-core/src/application/editor/operations/image/index.ts b/packages/ketcher-core/src/application/editor/operations/image/index.ts new file mode 100644 index 0000000000..2b64ae0e98 --- /dev/null +++ b/packages/ketcher-core/src/application/editor/operations/image/index.ts @@ -0,0 +1,3 @@ +export * from './imageMove'; +export * from './imageResize'; +export * from './imageUpsertDelete'; diff --git a/packages/ketcher-core/src/application/editor/operations/index.ts b/packages/ketcher-core/src/application/editor/operations/index.ts index 648f0df7f0..d0de9a3210 100644 --- a/packages/ketcher-core/src/application/editor/operations/index.ts +++ b/packages/ketcher-core/src/application/editor/operations/index.ts @@ -26,7 +26,7 @@ export * from './FragmentStereoFlag'; export * from './calcimplicitH'; export * from './LoopMove'; export * from './OperationType'; -export * from './rasterImage'; +export * from './image'; export * from './rgroup'; export * from './rgroupAttachmentPoint'; export * from './rxn'; diff --git a/packages/ketcher-core/src/application/editor/operations/rasterImage/index.ts b/packages/ketcher-core/src/application/editor/operations/rasterImage/index.ts deleted file mode 100644 index 0f7aa00695..0000000000 --- a/packages/ketcher-core/src/application/editor/operations/rasterImage/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './rasterImageMove'; -export * from './rasterImageResize'; -export * from './rasterImageUpsertDelete'; diff --git a/packages/ketcher-core/src/application/editor/shared/constants.ts b/packages/ketcher-core/src/application/editor/shared/constants.ts index ba3e2b7a16..524e851bff 100644 --- a/packages/ketcher-core/src/application/editor/shared/constants.ts +++ b/packages/ketcher-core/src/application/editor/shared/constants.ts @@ -14,7 +14,7 @@ * limitations under the License. ***************************************************************************/ -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { IMAGE_KEY } from 'domain/constants'; export const SgContexts = { Fragment: 'Fragment', @@ -35,7 +35,7 @@ export const selectionKeys = [ 'rxnPluses', 'simpleObjects', 'texts', - RASTER_IMAGE_KEY, + IMAGE_KEY, ] as const; export const defaultBondThickness = 2; diff --git a/packages/ketcher-core/src/application/render/restruct/generalEnumTypes.ts b/packages/ketcher-core/src/application/render/restruct/generalEnumTypes.ts index 9ebd57d196..71e9f8c4ec 100644 --- a/packages/ketcher-core/src/application/render/restruct/generalEnumTypes.ts +++ b/packages/ketcher-core/src/application/render/restruct/generalEnumTypes.ts @@ -22,7 +22,7 @@ export enum LayerMap { background = 'background', selectionPlate = 'selectionPlate', hovering = 'hovering', - rasterImages = 'rasterImages', + images = 'images', atom = 'atom', bondSkeleton = 'bondSkeleton', warnings = 'warnings', diff --git a/packages/ketcher-core/src/application/render/restruct/index.ts b/packages/ketcher-core/src/application/render/restruct/index.ts index d2e4a22d50..6b61c36eb6 100644 --- a/packages/ketcher-core/src/application/render/restruct/index.ts +++ b/packages/ketcher-core/src/application/render/restruct/index.ts @@ -32,7 +32,7 @@ import ReText from './retext'; export * from './generalEnumTypes'; export * from './reatom'; export * from './rergroupAttachmentPoint'; -export * from './rerasterImage'; +export * from './reImage'; export { ReObject, ReAtom, diff --git a/packages/ketcher-core/src/application/render/restruct/rerasterImage.ts b/packages/ketcher-core/src/application/render/restruct/reImage.ts similarity index 90% rename from packages/ketcher-core/src/application/render/restruct/rerasterImage.ts rename to packages/ketcher-core/src/application/render/restruct/reImage.ts index 83e38d9f4b..a3825c1fac 100644 --- a/packages/ketcher-core/src/application/render/restruct/rerasterImage.ts +++ b/packages/ketcher-core/src/application/render/restruct/reImage.ts @@ -1,34 +1,34 @@ import { LayerMap, ReObject, ReStruct } from 'application/render/restruct'; import { - RasterImage, - RasterImageReferenceName, - RasterImageReferencePositionInfo, -} from 'domain/entities/rasterImage'; + Image, + ImageReferenceName, + ImageReferencePositionInfo, +} from 'domain/entities/image'; import { RenderOptions } from 'application/render/render.types'; import { Scale } from 'domain/helpers'; import { RaphaelPaper, RaphaelSet } from 'raphael'; import { Box2Abs, Vec2 } from 'domain/entities'; import draw from 'application/render/draw'; -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { IMAGE_KEY } from 'domain/constants'; import { Render } from 'application/render'; -type GetReferencePositions = ReturnType; +type GetReferencePositions = ReturnType; const REFERENCE_POINT_LINE_WIDTH_MULTIPLIER = 0.4; interface ClosestReferencePosition { distance: number; - ref: RasterImageReferencePositionInfo | null; + ref: ImageReferencePositionInfo | null; } -export class ReRasterImage extends ReObject { +export class ReImage extends ReObject { private selectionPointsSet: RaphaelSet; static isSelectable(): boolean { return true; } - constructor(public rasterImage: RasterImage) { - super(RASTER_IMAGE_KEY); + constructor(public image: Image) { + super(IMAGE_KEY); } private getScaledPointWithOffset( @@ -46,11 +46,11 @@ export class ReRasterImage extends ReObject { private getDimensions(renderOptions: RenderOptions): Vec2 { return Vec2.diff( this.getScaledPointWithOffset( - this.rasterImage.getBottomRightPosition(), + this.image.getBottomRightPosition(), renderOptions, ), this.getScaledPointWithOffset( - this.rasterImage.getTopLeftPosition(), + this.image.getTopLeftPosition(), renderOptions, ), ); @@ -66,7 +66,7 @@ export class ReRasterImage extends ReObject { topRightPosition, bottomRightPosition, bottomLeftPosition, - ] = this.rasterImage + ] = this.image .getCornerPositions() .map((position) => Scale.modelToCanvas(position, renderOptions)); const selectionTopLeftPosition = topLeftPosition.sub( @@ -156,7 +156,7 @@ export class ReRasterImage extends ReObject { 'stroke-width': strokeWidth, }); if (element.node && element.node.setAttribute) { - element.node.setAttribute('data-testid', `rasterImageResize-${key}`); + element.node.setAttribute('data-testid', `imageResize-${key}`); } this.selectionPointsSet.push(element); @@ -170,16 +170,16 @@ export class ReRasterImage extends ReObject { show(restruct: ReStruct, renderOptions: RenderOptions) { const scaledTopLeftWithOffset = this.getScaledPointWithOffset( - this.rasterImage.getTopLeftPosition(), + this.image.getTopLeftPosition(), renderOptions, ); const dimensions = this.getDimensions(renderOptions); restruct.addReObjectPath( - LayerMap.rasterImages, + LayerMap.images, this.visel, restruct.render.paper.image( - this.rasterImage.bitmap, + this.image.bitmap, scaledTopLeftWithOffset.x, scaledTopLeftWithOffset.y, dimensions.x, @@ -219,8 +219,8 @@ export class ReRasterImage extends ReObject { getVBoxObj(): Box2Abs | null { return new Box2Abs( - this.rasterImage.getTopLeftPosition(), - this.rasterImage.getBottomRightPosition(), + this.image.getTopLeftPosition(), + this.image.getBottomRightPosition(), ); } @@ -255,7 +255,7 @@ export class ReRasterImage extends ReObject { ): ClosestReferencePosition { const entries = Object.entries( this.getSelectionReferencePositions(renderOptions), - ) as Array<[RasterImageReferenceName, Vec2]>; + ) as Array<[ImageReferenceName, Vec2]>; return entries.reduce( (acc, [key, position]) => { const offset = Vec2.diff(position, point); diff --git a/packages/ketcher-core/src/application/render/restruct/restruct.ts b/packages/ketcher-core/src/application/render/restruct/restruct.ts index 93ad7fba22..7922000b68 100644 --- a/packages/ketcher-core/src/application/render/restruct/restruct.ts +++ b/packages/ketcher-core/src/application/render/restruct/restruct.ts @@ -41,8 +41,8 @@ import { Render } from '../raphaelRender'; import Visel from './visel'; import util from '../util'; import { ReRGroupAttachmentPoint } from './rergroupAttachmentPoint'; -import { ReRasterImage } from 'application/render/restruct/rerasterImage'; -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { ReImage } from 'application/render/restruct/reImage'; +import { IMAGE_KEY } from 'domain/constants'; class ReStruct { public static readonly maps = { @@ -59,7 +59,7 @@ class ReStruct { reloops: ReLoop, simpleObjects: ReSimpleObject, texts: ReText, - [RASTER_IMAGE_KEY]: ReRasterImage, + [IMAGE_KEY]: ReImage, } as const; public render: Render; @@ -77,7 +77,7 @@ class ReStruct { public sgroupData: Map = new Map(); public enhancedFlags: Map = new Map(); public simpleObjects: Map = new Map(); - public rasterImages: Map = new Map(); + public images: Map = new Map(); public texts: Map = new Map(); private initialized = false; private layers: Array = []; @@ -93,7 +93,7 @@ class ReStruct { private enhancedFlagsChanged: Map = new Map(); private bondsChanged: Map = new Map(); private textsChanged: Map = new Map(); - private rasterImagesChanged: Map = new Map(); + private imagesChanged: Map = new Map(); private snappingBonds: number[] = []; constructor( @@ -161,8 +161,8 @@ class ReStruct { this.sgroupData.set(id, new ReDataSGroupData(item)); } }); - molecule.rasterImages.forEach((item, id) => { - this.rasterImages.set(id, new ReRasterImage(item)); + molecule.images.forEach((item, id) => { + this.images.set(id, new ReImage(item)); }); } @@ -724,8 +724,8 @@ class ReStruct { showImages() { const options = this.render.options; - this.rasterImagesChanged.forEach((_, id) => { - const image = this.rasterImages.get(id); + this.imagesChanged.forEach((_, id) => { + const image = this.images.get(id); if (image) { image.show(this, options); } diff --git a/packages/ketcher-core/src/domain/constants/rasterImage.ts b/packages/ketcher-core/src/domain/constants/image.ts similarity index 66% rename from packages/ketcher-core/src/domain/constants/rasterImage.ts rename to packages/ketcher-core/src/domain/constants/image.ts index e2b98a124c..61fece8219 100644 --- a/packages/ketcher-core/src/domain/constants/rasterImage.ts +++ b/packages/ketcher-core/src/domain/constants/image.ts @@ -1,15 +1,15 @@ -import type { RasterImageReferenceName } from 'domain/entities'; +import type { ImageReferenceName } from 'domain/entities'; -export const RASTER_IMAGE_KEY = 'rasterImages'; -export const RASTER_IMAGE_SERIALIZE_KEY = 'rasterImage'; +export const IMAGE_KEY = 'images'; +export const IMAGE_SERIALIZE_KEY = 'image'; const CURSOR_DIAGONAL_NWSE = 'nwse-resize'; const CURSOR_DIAGONAL_NESW = 'nesw-resize'; const CURSOR_VERTICAL = 'ns-resize'; const CURSOR_HORIZONTAL = 'ew-resize'; -export const rasterImageReferencePositionToCursor: Record< - RasterImageReferenceName, +export const imageReferencePositionToCursor: Record< + ImageReferenceName, string > = { topLeftPosition: CURSOR_DIAGONAL_NWSE, diff --git a/packages/ketcher-core/src/domain/constants/index.ts b/packages/ketcher-core/src/domain/constants/index.ts index fd6a9024a1..bb70e9f6bc 100644 --- a/packages/ketcher-core/src/domain/constants/index.ts +++ b/packages/ketcher-core/src/domain/constants/index.ts @@ -2,4 +2,4 @@ export * from './elementColor'; export * from './elements'; export * from './element.types'; export * from './generics'; -export * from './rasterImage'; +export * from './image'; diff --git a/packages/ketcher-core/src/domain/entities/rasterImage.ts b/packages/ketcher-core/src/domain/entities/image.ts similarity index 66% rename from packages/ketcher-core/src/domain/entities/rasterImage.ts rename to packages/ketcher-core/src/domain/entities/image.ts index a313680c08..a15bbfc87b 100644 --- a/packages/ketcher-core/src/domain/entities/rasterImage.ts +++ b/packages/ketcher-core/src/domain/entities/image.ts @@ -15,16 +15,22 @@ ***************************************************************************/ import { BaseMicromoleculeEntity } from 'domain/entities/BaseMicromoleculeEntity'; -import { Point, Vec2 } from 'domain/entities/vec2'; +import { Vec2 } from 'domain/entities/vec2'; import { getNodeWithInvertedYCoord, KetFileNode } from 'domain/serializers'; -import { RASTER_IMAGE_SERIALIZE_KEY } from 'domain/constants'; - -interface KetFileNodeContent { - bitmap: string; - halfSize: Point; +import { IMAGE_SERIALIZE_KEY } from 'domain/constants'; + +export interface KetFileImageNode extends KetFileNode { + format: string; + boundingBox: { + x: number; + y: number; + z?: number; + width: number; + height: number; + }; } -export interface RasterImageReferencePositions { +export interface ImageReferencePositions { topLeftPosition: Vec2; topMiddlePosition: Vec2; topRightPosition: Vec2; @@ -35,14 +41,14 @@ export interface RasterImageReferencePositions { leftMiddlePosition: Vec2; } -export type RasterImageReferenceName = keyof RasterImageReferencePositions; +export type ImageReferenceName = keyof ImageReferencePositions; -export interface RasterImageReferencePositionInfo { - name: RasterImageReferenceName; +export interface ImageReferencePositionInfo { + name: ImageReferenceName; offset: Vec2; } -export class RasterImage extends BaseMicromoleculeEntity { +export class Image extends BaseMicromoleculeEntity { constructor( public bitmap: string, private _center: Vec2, @@ -82,7 +88,7 @@ export class RasterImage extends BaseMicromoleculeEntity { ]; } - getReferencePositions(): RasterImageReferencePositions { + getReferencePositions(): ImageReferencePositions { const [ topLeftPosition, topRightPosition, @@ -104,8 +110,8 @@ export class RasterImage extends BaseMicromoleculeEntity { }; } - clone(): RasterImage { - return new RasterImage( + clone(): Image { + return new Image( this.bitmap, new Vec2(this._center), new Vec2(this.halfSize), @@ -132,32 +138,38 @@ export class RasterImage extends BaseMicromoleculeEntity { return this._center; } - toKetNode(): KetFileNode { + toKetNode(): KetFileImageNode { + const topLeftCorner = this.getTopLeftPosition(); + const base64Data = this.bitmap.replace(/^.*;base64,/, ''); + const format = this.bitmap.match( + /^data:(image\/.*);base64,/, + )?.[1] as string; return { - type: RASTER_IMAGE_SERIALIZE_KEY, + type: IMAGE_SERIALIZE_KEY, center: getNodeWithInvertedYCoord(this._center), - data: { - bitmap: this.bitmap, - halfSize: this.halfSize, + format, + boundingBox: { + ...getNodeWithInvertedYCoord(topLeftCorner), + width: this.halfSize.x * 2, + height: this.halfSize.y * 2, }, + data: base64Data, + selected: this.getInitiallySelected(), }; } - static fromKetNode( - ketFileNode: KetFileNode, - ): RasterImage { - const vectorCenter = new Vec2( - getNodeWithInvertedYCoord(ketFileNode.center), + static fromKetNode(ketFileNode: KetFileImageNode): Image { + const { width, height, ...point } = getNodeWithInvertedYCoord( + ketFileNode.boundingBox, ); + const halfSize = new Vec2(width / 2, height / 2); + const topLeftCorner = new Vec2(point); + const center = topLeftCorner.add(halfSize); + const imageSrc = `data:${ketFileNode.format};base64,${ketFileNode.data}`; + // Should be validated already - const data = ketFileNode.data as KetFileNodeContent; - const vectorHalfSize = new Vec2(data.halfSize); - const rasterImage = new RasterImage( - data.bitmap, - vectorCenter, - vectorHalfSize, - ); - rasterImage.setInitiallySelected(ketFileNode.selected); - return rasterImage; + const image = new Image(imageSrc, center, halfSize); + image.setInitiallySelected(ketFileNode.selected); + return image; } } diff --git a/packages/ketcher-core/src/domain/entities/index.ts b/packages/ketcher-core/src/domain/entities/index.ts index dea197e263..3a50e39a9e 100644 --- a/packages/ketcher-core/src/domain/entities/index.ts +++ b/packages/ketcher-core/src/domain/entities/index.ts @@ -34,7 +34,7 @@ export * from './pile'; export * from './vec2'; export * from './box2Abs'; export * from './pool'; -export * from './rasterImage'; +export * from './image'; export * from './highlight'; export * from './sGroupAttachmentPoint'; export * from './monomerMicromolecule'; diff --git a/packages/ketcher-core/src/domain/entities/struct.ts b/packages/ketcher-core/src/domain/entities/struct.ts index 3727ee6052..af8f74467d 100644 --- a/packages/ketcher-core/src/domain/entities/struct.ts +++ b/packages/ketcher-core/src/domain/entities/struct.ts @@ -38,7 +38,7 @@ import { Highlight } from './highlight'; import { RGroupAttachmentPoint } from './rgroupAttachmentPoint'; import { MonomerMicromolecule } from 'domain/entities/monomerMicromolecule'; import { isNumber } from 'lodash'; -import { RasterImage } from './rasterImage'; +import { Image } from './image'; export type Neighbor = { aid: number; @@ -74,7 +74,7 @@ export class Struct { abbreviation?: string; sGroupForest: SGroupForest; simpleObjects: Pool; - rasterImages: Pool; + images: Pool; texts: Pool; functionalGroups: Pool; highlights: Pool; @@ -98,7 +98,7 @@ export class Struct { this.texts = new Pool(); this.functionalGroups = new Pool(); this.highlights = new Pool(); - this.rasterImages = new Pool(); + this.images = new Pool(); } hasRxnProps(): boolean { @@ -127,7 +127,7 @@ export class Struct { this.rxnPluses.size === 0 && this.simpleObjects.size === 0 && this.texts.size === 0 && - this.rasterImages.size === 0 + this.images.size === 0 ); } @@ -145,7 +145,7 @@ export class Struct { simpleObjectsSet?: Pile | null, textsSet?: Pile | null, rgroupAttachmentPointSet?: Pile | null, - rasterImagesSet?: Pile | null, + imagesSet?: Pile | null, bidMap?: Map | null, ): Struct { return this.mergeInto( @@ -158,7 +158,7 @@ export class Struct { simpleObjectsSet, textsSet, rgroupAttachmentPointSet, - rasterImagesSet, + imagesSet, bidMap, ); } @@ -217,7 +217,7 @@ export class Struct { simpleObjectsSet?: Pile | null, textsSet?: Pile | null, rgroupAttachmentPointSet?: Pile | null, - rasterImagesSet?: Pile | null, + imagesSet?: Pile | null, bidMapEntity?: Map | null, ): Struct { atomSet = atomSet || new Pile(this.atoms.keys()); @@ -225,8 +225,7 @@ export class Struct { simpleObjectsSet = simpleObjectsSet || new Pile(this.simpleObjects.keys()); textsSet = textsSet || new Pile(this.texts.keys()); - rasterImagesSet = - rasterImagesSet || new Pile(this.rasterImages.keys()); + imagesSet = imagesSet || new Pile(this.images.keys()); rgroupAttachmentPointSet = rgroupAttachmentPointSet || new Pile(this.rgroupAttachmentPoints.keys()); @@ -339,8 +338,8 @@ export class Struct { cp.texts.add(this.texts.get(id)!.clone()); }); - rasterImagesSet.forEach((id) => { - cp.rasterImages.add(this.rasterImages.get(id)!.clone()); + imagesSet.forEach((id) => { + cp.images.add(this.images.get(id)!.clone()); }); rgroupAttachmentPointSet.forEach((id) => { @@ -841,7 +840,7 @@ export class Struct { simpleObjects.pos = simpleObjects.pos.map((p) => p.scaled(scale)); }); - this.rasterImages.forEach((rasterImage) => rasterImage.rescaleSize(scale)); + this.images.forEach((image) => image.rescaleSize(scale)); } rescale() { diff --git a/packages/ketcher-core/src/domain/serializers/ket/fromKet/rasterImageToStruct.ts b/packages/ketcher-core/src/domain/serializers/ket/fromKet/imageToStruct.ts similarity index 81% rename from packages/ketcher-core/src/domain/serializers/ket/fromKet/rasterImageToStruct.ts rename to packages/ketcher-core/src/domain/serializers/ket/fromKet/imageToStruct.ts index 135be35761..16b1805af6 100644 --- a/packages/ketcher-core/src/domain/serializers/ket/fromKet/rasterImageToStruct.ts +++ b/packages/ketcher-core/src/domain/serializers/ket/fromKet/imageToStruct.ts @@ -15,10 +15,10 @@ ***************************************************************************/ import { Struct } from 'domain/entities'; -import { RasterImage } from 'domain/entities/rasterImage'; +import { Image } from 'domain/entities/image'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function rasterImageToStruct(ketItem: any, struct: Struct): Struct { - struct.rasterImages.add(RasterImage.fromKetNode(ketItem)); +export function imageToStruct(ketItem: any, struct: Struct): Struct { + struct.images.add(Image.fromKetNode(ketItem)); return struct; } diff --git a/packages/ketcher-core/src/domain/serializers/ket/ketSerializer.ts b/packages/ketcher-core/src/domain/serializers/ket/ketSerializer.ts index 727bdf9d74..fcd2ae7d3a 100644 --- a/packages/ketcher-core/src/domain/serializers/ket/ketSerializer.ts +++ b/packages/ketcher-core/src/domain/serializers/ket/ketSerializer.ts @@ -77,9 +77,9 @@ import { getAttachmentPointLabelWithBinaryShift } from 'domain/helpers/attachmen import { isNumber } from 'lodash'; import { MonomerItemType } from 'domain/types'; import { PolymerBond } from 'domain/entities/PolymerBond'; -import { rasterImageToKet } from 'domain/serializers/ket/toKet/rasterImageToKet'; -import { rasterImageToStruct } from 'domain/serializers/ket/fromKet/rasterImageToStruct'; -import { RASTER_IMAGE_SERIALIZE_KEY } from 'domain/constants'; +import { imageToKet } from 'domain/serializers/ket/toKet/imageToKet'; +import { imageToStruct } from 'domain/serializers/ket/fromKet/imageToStruct'; +import { IMAGE_SERIALIZE_KEY } from 'domain/constants'; function parseNode(node: any, struct: any) { const type = node.type; @@ -114,8 +114,8 @@ function parseNode(node: any, struct: any) { textToStruct(node, struct); break; } - case RASTER_IMAGE_SERIALIZE_KEY: { - rasterImageToStruct(node, struct); + case IMAGE_SERIALIZE_KEY: { + imageToStruct(node, struct); break; } default: @@ -188,8 +188,8 @@ export class KetSerializer implements Serializer { result.root.nodes.push(textToKet(item)); break; } - case RASTER_IMAGE_SERIALIZE_KEY: { - result.root.nodes.push(rasterImageToKet(item)); + case IMAGE_SERIALIZE_KEY: { + result.root.nodes.push(imageToKet(item)); break; } default: diff --git a/packages/ketcher-core/src/domain/serializers/ket/schema.json b/packages/ketcher-core/src/domain/serializers/ket/schema.json index 0d61d5c1e9..71f646c756 100644 --- a/packages/ketcher-core/src/domain/serializers/ket/schema.json +++ b/packages/ketcher-core/src/domain/serializers/ket/schema.json @@ -27,7 +27,7 @@ "$ref": "#/definitions/plus" }, { - "$ref": "#/definitions/rasterImage" + "$ref": "#/definitions/image" }, { "type": "object", @@ -58,23 +58,6 @@ }, "additionalProperties": false, "definitions": { - "2dCoordinates": { - "type": "object", - "required": ["x", "y"], - "properties": { - "x": { - "type": "number" - }, - "y": { - "type": "number" - } - } - }, - "imageFile": { - "type": "string", - "pattern": "^data:image/(png|svg\\+xml);base64,", - "minLength": 160 - }, "header": { "type": "object", "properties": { @@ -798,38 +781,43 @@ } } }, - "rasterImage": { + "image": { "type": "object", - "required": ["type", "data"], + "required": ["type", "format", "boundingBox", "data"], "properties": { "type": { - "const": "rasterImage" + "const": "image" }, - "center": { - "$ref": "#/definitions/2dCoordinates" + "format": { + "type": "string", + "pattern": "^image/(png|svg\\+xml)$" }, - "data": { + "boundingBox": { "type": "object", - "required": ["bitmap", "halfSize"], + "required": ["width", "height", "x", "y"], "properties": { - "bitmap": { - "$ref": "#/definitions/imageFile" + "width": { + "type": "number", + "exclusiveMinimum": 0 }, - "halfSize": { - "type": "object", - "required": ["x", "y"], - "properties": { - "x": { - "type": "number", - "exclusiveMinimum": 0 - }, - "y": { - "type": "number", - "exclusiveMinimum": 0 - } - } + "height": { + "type": "number", + "exclusiveMinimum": 0 + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "z": { + "type": "number" } } + }, + "data": { + "type": "string", + "minLength": 160 } } } diff --git a/packages/ketcher-core/src/domain/serializers/ket/toKet/rasterImageToKet.ts b/packages/ketcher-core/src/domain/serializers/ket/toKet/imageToKet.ts similarity index 64% rename from packages/ketcher-core/src/domain/serializers/ket/toKet/rasterImageToKet.ts rename to packages/ketcher-core/src/domain/serializers/ket/toKet/imageToKet.ts index 3887a96c30..c5e2fa4a7d 100644 --- a/packages/ketcher-core/src/domain/serializers/ket/toKet/rasterImageToKet.ts +++ b/packages/ketcher-core/src/domain/serializers/ket/toKet/imageToKet.ts @@ -14,13 +14,16 @@ * limitations under the License. ***************************************************************************/ -import { RASTER_IMAGE_SERIALIZE_KEY } from 'domain/constants'; +import { IMAGE_SERIALIZE_KEY } from 'domain/constants'; +import { KetFileNode } from 'domain/serializers'; +import { KetFileImageNode } from 'domain/entities'; -export function rasterImageToKet(rasterImageNode) { +export function imageToKet(imageNode: KetFileNode) { return { - type: RASTER_IMAGE_SERIALIZE_KEY, - center: rasterImageNode.center, - data: rasterImageNode.data, - selected: rasterImageNode.selected, + type: IMAGE_SERIALIZE_KEY, + format: (imageNode as KetFileImageNode).format, + boundingBox: (imageNode as KetFileImageNode).boundingBox, + data: imageNode.data, + selected: imageNode.selected, }; } diff --git a/packages/ketcher-core/src/domain/serializers/ket/toKet/prepare.ts b/packages/ketcher-core/src/domain/serializers/ket/toKet/prepare.ts index 92845add72..36f284d748 100644 --- a/packages/ketcher-core/src/domain/serializers/ket/toKet/prepare.ts +++ b/packages/ketcher-core/src/domain/serializers/ket/toKet/prepare.ts @@ -89,7 +89,7 @@ export function prepareStructForKet(struct: Struct) { }); }); - struct.rasterImages.forEach((image) => { + struct.images.forEach((image) => { ketNodes.push(image.toKetNode()); }); diff --git a/packages/ketcher-react/src/components/Icon/utils/iconNameToIcon.ts b/packages/ketcher-react/src/components/Icon/utils/iconNameToIcon.ts index f023dfe38a..2cd2d6d417 100644 --- a/packages/ketcher-react/src/components/Icon/utils/iconNameToIcon.ts +++ b/packages/ketcher-react/src/components/Icon/utils/iconNameToIcon.ts @@ -225,7 +225,7 @@ import SnakeLayoutIcon from '../../../assets/icons/files/snake-layout-mode.svg'; import SequenceLayoutIcon from '../../../assets/icons/files/sequence-layout-mode.svg'; import QuestionMark from '../../../assets/icons/files/questionMark.svg'; import Nucleotide from '../../../assets/icons/files/nucleotide.svg'; -import { RASTER_IMAGE_KEY } from 'ketcher-core'; +import { IMAGE_KEY } from 'ketcher-core'; export const iconNameToIcon = { α, @@ -391,7 +391,7 @@ export const iconNameToIcon = { 'template-lib': TemplateLibIcon, 'snake-mode': SnakeModeIcon, text: TextIcon, - [RASTER_IMAGE_KEY]: AddImageIcon, + [IMAGE_KEY]: AddImageIcon, 'text-bold': TextBold, 'text-italic': TextItalic, 'text-subscript': TextSubscript, diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index 4daeca950f..d6ab4da04c 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -28,7 +28,7 @@ import { fromNewCanvas, provideEditorSettings, ReStruct, - RASTER_IMAGE_KEY, + IMAGE_KEY, } from 'ketcher-core'; import { DOMSubscription, @@ -67,7 +67,7 @@ const structObjects: Array = [ 'enhancedFlags', 'simpleObjects', 'texts', - RASTER_IMAGE_KEY, + IMAGE_KEY, ]; const highlightTargets = [ @@ -85,7 +85,7 @@ const highlightTargets = [ 'enhancedFlags', 'simpleObjects', 'texts', - RASTER_IMAGE_KEY, + IMAGE_KEY, ]; function selectStereoFlagsIfNecessary( @@ -670,7 +670,7 @@ class Editor implements KetcherEditor { new Pile(selection.simpleObjects), new Pile(selection.texts), null, - new Pile(selection.rasterImages), + new Pile(selection.images), ); // Copy by its own as Struct.clone doesn't support diff --git a/packages/ketcher-react/src/script/editor/shared/closest.ts b/packages/ketcher-react/src/script/editor/shared/closest.ts index f2a42b7baa..d99648db5f 100644 --- a/packages/ketcher-react/src/script/editor/shared/closest.ts +++ b/packages/ketcher-react/src/script/editor/shared/closest.ts @@ -23,8 +23,8 @@ import { ReStruct, Atom, Bond, - RASTER_IMAGE_KEY, - RasterImageReferencePositionInfo, + IMAGE_KEY, + ImageReferencePositionInfo, } from 'ketcher-core'; import { ClosestItem, ClosestItemWithMap } from './closest.types'; @@ -45,7 +45,7 @@ const findMaps = { rgroupAttachmentPoints: findClosestRgroupAttachmentPoints, simpleObjects: findClosestSimpleObject, texts: findClosestText, - [RASTER_IMAGE_KEY]: findClosestRasterImage, + [IMAGE_KEY]: findClosestImage, }; type ClosestReturnType = ClosestItem | null; @@ -703,7 +703,7 @@ function mergeAtomToFunctionalGroup( return false; } -function findClosestRasterImage(reStruct: ReStruct, cursorPosition: Vec2) { +function findClosestImage(reStruct: ReStruct, cursorPosition: Vec2) { const renderOptions = reStruct.render.options; const canvasScaledPosition = Scale.modelToCanvas( cursorPosition, @@ -711,8 +711,8 @@ function findClosestRasterImage(reStruct: ReStruct, cursorPosition: Vec2) { ); const maxDistance = renderOptions.microModeScale * SELECTION_DISTANCE_COEFFICIENT; - return Array.from(reStruct.rasterImages.entries()).reduce( - (acc: ClosestReturnType, [id, item]) => { + return Array.from(reStruct.images.entries()).reduce( + (acc: ClosestReturnType, [id, item]) => { const distanceToPoint = item.calculateDistanceToPoint( canvasScaledPosition, renderOptions, diff --git a/packages/ketcher-react/src/script/editor/tool/eraser.ts b/packages/ketcher-react/src/script/editor/tool/eraser.ts index 799c2bb591..ab7e2f9773 100644 --- a/packages/ketcher-react/src/script/editor/tool/eraser.ts +++ b/packages/ketcher-react/src/script/editor/tool/eraser.ts @@ -20,14 +20,14 @@ import { fromOneAtomDeletion, fromOneBondDeletion, fromPlusDeletion, - fromRasterImageDeletion, + fromImageDeletion, fromRGroupAttachmentPointDeletion, fromSgroupDeletion, fromSimpleObjectDeletion, fromTextDeletion, FunctionalGroup, SGroup, - RASTER_IMAGE_KEY, + IMAGE_KEY, } from 'ketcher-core'; import LassoHelper from './helper/lasso'; @@ -54,7 +54,7 @@ class EraserTool implements Tool { 'simpleObjects', 'texts', 'rgroupAttachmentPoints', - RASTER_IMAGE_KEY, + IMAGE_KEY, ]; this.lassoHelper = new LassoHelper(mode || 0, editor, null); @@ -371,8 +371,8 @@ class EraserTool implements Tool { this.editor.update(fromTextDeletion(restruct, ci.id)); } else if (ci.map === 'rgroupAttachmentPoints') { this.editor.update(fromRGroupAttachmentPointDeletion(restruct, ci.id)); - } else if (ci.map === RASTER_IMAGE_KEY) { - this.editor.update(fromRasterImageDeletion(restruct, ci.id)); + } else if (ci.map === IMAGE_KEY) { + this.editor.update(fromImageDeletion(restruct, ci.id)); } else { // TODO re-factoring needed - should be "map-independent" console.error( diff --git a/packages/ketcher-react/src/script/editor/tool/helper/locate.ts b/packages/ketcher-react/src/script/editor/tool/helper/locate.ts index 49ed8fa2d1..394e599049 100644 --- a/packages/ketcher-react/src/script/editor/tool/helper/locate.ts +++ b/packages/ketcher-react/src/script/editor/tool/helper/locate.ts @@ -17,7 +17,7 @@ import { FunctionalGroup, MonomerMicromolecule, - RASTER_IMAGE_KEY, + IMAGE_KEY, Struct, Vec2, ReStruct, @@ -175,10 +175,10 @@ function getElementsInRectangle(restruct: ReStruct, p0, p1) { } }); - const rerasterImages = Array.from(restruct.rasterImages.entries()).reduce( + const reImages = Array.from(restruct.images.entries()).reduce( (acc: Array, [id, item]): Array => { if ( - Object.values(item.rasterImage.getReferencePositions()).some((point) => + Object.values(item.image.getReferencePositions()).some((point) => point.isInsidePolygon([ topLeftPosition, topRightPosition, @@ -204,7 +204,7 @@ function getElementsInRectangle(restruct: ReStruct, p0, p1) { simpleObjects: simpleObjectsList, texts: textsList, rgroupAttachmentPoints: rgroupAttachmentPointList, - [RASTER_IMAGE_KEY]: rerasterImages, + [IMAGE_KEY]: reImages, }; } @@ -335,10 +335,10 @@ function getElementsInPolygon(restruct: ReStruct, rr) { } }); - const rerasterImages = Array.from(restruct.rasterImages.entries()).reduce( + const reImages = Array.from(restruct.images.entries()).reduce( (acc: Array, [id, item]) => { if ( - Object.values(item.rasterImage.getReferencePositions()).some((point) => + Object.values(item.image.getReferencePositions()).some((point) => isPointInPolygon(r, point), ) ) { @@ -359,7 +359,7 @@ function getElementsInPolygon(restruct: ReStruct, rr) { simpleObjects: simpleObjectsList, texts: textsList, rgroupAttachmentPoints: rgroupAttachmentPointList, - [RASTER_IMAGE_KEY]: rerasterImages, + [IMAGE_KEY]: reImages, }; } diff --git a/packages/ketcher-react/src/script/editor/tool/rasterImage.ts b/packages/ketcher-react/src/script/editor/tool/image.ts similarity index 84% rename from packages/ketcher-react/src/script/editor/tool/rasterImage.ts rename to packages/ketcher-react/src/script/editor/tool/image.ts index b119bbe56e..fe2708e4af 100644 --- a/packages/ketcher-react/src/script/editor/tool/rasterImage.ts +++ b/packages/ketcher-react/src/script/editor/tool/image.ts @@ -2,21 +2,21 @@ import { CoordinateTransformation, Scale, Vec2, - fromRasterImageCreation, + fromImageCreation, KetcherLogger, Action, - RASTER_IMAGE_KEY, - fromRasterImageMove, - fromRasterImageResize, - RasterImageReferencePositionInfo, - rasterImageReferencePositionToCursor, + IMAGE_KEY, + fromImageMove, + fromImageResize, + ImageReferencePositionInfo, + imageReferencePositionToCursor, } from 'ketcher-core'; import { Tool } from './Tool'; import type Editor from '../Editor'; import { ClosestItemWithMap } from '../shared/closest.types'; import { handleMovingPosibilityCursor } from '../utils'; -const TAG = 'tool/rasterImage.ts'; +const TAG = 'tool/image.ts'; const supportedMimes = ['png', 'svg+xml']; const supportedMimesForRegex = supportedMimes @@ -29,10 +29,10 @@ const MIN_DIMENSION_SIZE = 16; interface DragContext { center: Vec2; action: Action; - closestItem: ClosestItemWithMap; + closestItem: ClosestItemWithMap; } -export class RasterImageTool implements Tool { +export class ImageTool implements Tool { static readonly INPUT_ID = 'image-upload'; private element: HTMLInputElement; private dragCtx: DragContext | null = null; @@ -44,13 +44,13 @@ export class RasterImageTool implements Tool { mousedown(event: MouseEvent) { const render = this.editor.render; const closestItem = this.editor.findItem(event, [ - RASTER_IMAGE_KEY, - ]) as ClosestItemWithMap; + IMAGE_KEY, + ]) as ClosestItemWithMap; this.editor.selection(null); if (closestItem) { this.editor.hover(null); - this.editor.selection({ [RASTER_IMAGE_KEY]: [closestItem.id] }); + this.editor.selection({ [IMAGE_KEY]: [closestItem.id] }); this.dragCtx = { center: CoordinateTransformation.pageToModel(event, render), action: new Action(), @@ -60,7 +60,7 @@ export class RasterImageTool implements Tool { } click(event: MouseEvent) { - const closestItem = this.editor.findItem(event, [RASTER_IMAGE_KEY]); + const closestItem = this.editor.findItem(event, [IMAGE_KEY]); this.editor.hover(null); if (closestItem) { return; @@ -81,13 +81,13 @@ export class RasterImageTool implements Tool { const click = CoordinateTransformation.pageToModel(event, render); this.dragCtx.action = this.dragCtx.closestItem.ref - ? fromRasterImageResize( + ? fromImageResize( render.ctab, this.dragCtx.closestItem.id, click, this.dragCtx.closestItem.ref, ) - : fromRasterImageMove( + : fromImageMove( render.ctab, this.dragCtx.closestItem.id, click.sub(this.dragCtx.center), @@ -95,15 +95,15 @@ export class RasterImageTool implements Tool { this.editor.update(this.dragCtx.action, true); } else { const item = this.editor.findItem(event, [ - RASTER_IMAGE_KEY, - ]) as ClosestItemWithMap; + IMAGE_KEY, + ]) as ClosestItemWithMap; const render = this.editor.render; if (item?.ref) { handleMovingPosibilityCursor( item, render.paper.canvas, - rasterImageReferencePositionToCursor[item.ref.name], + imageReferencePositionToCursor[item.ref.name], ); } else { handleMovingPosibilityCursor( @@ -168,7 +168,7 @@ export class RasterImageTool implements Tool { ); this.editor.update( - fromRasterImageCreation( + fromImageCreation( this.editor.render.ctab, image.src, clickPosition, @@ -193,7 +193,7 @@ export class RasterImageTool implements Tool { private createElement(): HTMLInputElement { const uploader = document.createElement('input'); uploader.style.display = 'none'; - uploader.id = RasterImageTool.INPUT_ID; + uploader.id = ImageTool.INPUT_ID; uploader.type = 'file'; uploader.accept = supportedMimes.map((item) => `image/${item}`).join(','); document.body.appendChild(uploader); @@ -201,7 +201,7 @@ export class RasterImageTool implements Tool { } private getElement(): HTMLInputElement { - const element = document.getElementById(RasterImageTool.INPUT_ID); + const element = document.getElementById(ImageTool.INPUT_ID); if (element instanceof HTMLInputElement) { return element; diff --git a/packages/ketcher-react/src/script/editor/tool/index.ts b/packages/ketcher-react/src/script/editor/tool/index.ts index 8726a34beb..277a5a3ca1 100644 --- a/packages/ketcher-react/src/script/editor/tool/index.ts +++ b/packages/ketcher-react/src/script/editor/tool/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ -import { RASTER_IMAGE_KEY } from 'ketcher-core'; +import { IMAGE_KEY } from 'ketcher-core'; import APointTool from './apoint'; import AtomTool from './atom'; @@ -38,7 +38,7 @@ import SimpleObjectTool from './simpleobject'; import TemplateTool from './template'; import TextTool from './text'; import { ToolConstructorInterface } from './Tool'; -import { RasterImageTool } from './rasterImage'; +import { ImageTool } from './image'; export const toolsMap: Record = { hand: HandTool, @@ -63,5 +63,5 @@ export const toolsMap: Record = { enhancedStereo: EnhancedStereoTool, simpleobject: SimpleObjectTool, text: TextTool, - [RASTER_IMAGE_KEY]: RasterImageTool, + [IMAGE_KEY]: ImageTool, }; diff --git a/packages/ketcher-react/src/script/editor/tool/select.ts b/packages/ketcher-react/src/script/editor/tool/select.ts index f12916ec8a..ed983b05c3 100644 --- a/packages/ketcher-react/src/script/editor/tool/select.ts +++ b/packages/ketcher-react/src/script/editor/tool/select.ts @@ -33,10 +33,10 @@ import { vectorUtils, KetcherLogger, CoordinateTransformation, - RASTER_IMAGE_KEY, - rasterImageReferencePositionToCursor, - RasterImageReferencePositionInfo, - fromRasterImageResize, + IMAGE_KEY, + imageReferencePositionToCursor, + ImageReferencePositionInfo, + fromImageResize, } from 'ketcher-core'; import LassoHelper from './helper/lasso'; @@ -199,11 +199,11 @@ class SelectTool implements Tool { } /* end */ - /* handle raster image resize */ - if (dragCtx.item.map === RASTER_IMAGE_KEY && dragCtx.item.ref) { + /* handle image resize */ + if (dragCtx.item.map === IMAGE_KEY && dragCtx.item.ref) { if (dragCtx.action) dragCtx.action.perform(rnd.ctab); const position = CoordinateTransformation.pageToModel(event, rnd); - dragCtx.action = fromRasterImageResize( + dragCtx.action = fromImageResize( rnd.ctab, dragCtx.item.id, position, @@ -278,14 +278,13 @@ class SelectTool implements Tool { ); const item = editor.findItem(event, maps, null); editor.hover(item, null, event); - if (item?.map === RASTER_IMAGE_KEY && item.ref) { - const referencePositionInfo = - item.ref as RasterImageReferencePositionInfo; + if (item?.map === IMAGE_KEY && item.ref) { + const referencePositionInfo = item.ref as ImageReferencePositionInfo; handleMovingPosibilityCursor( item, this.editor.render.paper.canvas, // Casting is safe because we've checked for item map - rasterImageReferencePositionToCursor[referencePositionInfo.name], + imageReferencePositionToCursor[referencePositionInfo.name], ); } else { handleMovingPosibilityCursor( @@ -717,7 +716,7 @@ function getMapsForClosestItem(selectFragment: boolean) { 'enhancedFlags', 'simpleObjects', 'texts', - RASTER_IMAGE_KEY, + IMAGE_KEY, ...(selectFragment ? ['frags'] : ['atoms', 'bonds']), ]; } diff --git a/packages/ketcher-react/src/script/ui/action/tools.js b/packages/ketcher-react/src/script/ui/action/tools.js index 1c380366fd..5a4848ac9f 100644 --- a/packages/ketcher-react/src/script/ui/action/tools.js +++ b/packages/ketcher-react/src/script/ui/action/tools.js @@ -18,7 +18,7 @@ import { RxnArrowMode, SimpleObjectMode, findStereoAtoms, - RASTER_IMAGE_KEY, + IMAGE_KEY, } from 'ketcher-core'; import { bond as bondSchema } from '../data/schema/struct-schema'; @@ -320,10 +320,10 @@ const toolActions = { bonds: { hidden: (options) => isHidden(options, 'bonds'), }, - [RASTER_IMAGE_KEY]: { + [IMAGE_KEY]: { title: 'Add Image', - action: { tool: RASTER_IMAGE_KEY }, - hidden: (options) => isHidden(options, RASTER_IMAGE_KEY), + action: { tool: IMAGE_KEY }, + hidden: (options) => isHidden(options, IMAGE_KEY), }, }; diff --git a/packages/ketcher-react/src/script/ui/views/toolbars/LeftToolbar/LeftToolbar.tsx b/packages/ketcher-react/src/script/ui/views/toolbars/LeftToolbar/LeftToolbar.tsx index b7def45759..94bdf09188 100644 --- a/packages/ketcher-react/src/script/ui/views/toolbars/LeftToolbar/LeftToolbar.tsx +++ b/packages/ketcher-react/src/script/ui/views/toolbars/LeftToolbar/LeftToolbar.tsx @@ -15,7 +15,7 @@ ***************************************************************************/ import { FC, MutableRefObject, useRef } from 'react'; -import { RASTER_IMAGE_KEY } from 'ketcher-core'; +import { IMAGE_KEY } from 'ketcher-core'; import { ToolbarGroupItem, ToolbarGroupItemCallProps, @@ -189,7 +189,7 @@ const LeftToolbar = (props: Props) => { items={[ { id: 'shapes', options: shapeOptions }, { id: 'text' }, - { id: RASTER_IMAGE_KEY }, + { id: IMAGE_KEY }, ]} /> diff --git a/packages/ketcher-react/src/script/ui/views/toolbars/toolbar.types.ts b/packages/ketcher-react/src/script/ui/views/toolbars/toolbar.types.ts index 323841cfa2..3de0b25ff0 100644 --- a/packages/ketcher-react/src/script/ui/views/toolbars/toolbar.types.ts +++ b/packages/ketcher-react/src/script/ui/views/toolbars/toolbar.types.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ -import { RASTER_IMAGE_KEY } from 'domain/constants'; +import { IMAGE_KEY } from 'domain/constants'; type TopGroup = 'document' | 'edit' | 'zoom' | 'process' | 'meta'; @@ -137,7 +137,7 @@ type LeftToolbarItemVariant = // text group | 'text' // image group - | typeof RASTER_IMAGE_KEY; + | typeof IMAGE_KEY; type BottomToolbarItemVariant = | 'template-common' diff --git a/packages/ketcher-standalone/package.json b/packages/ketcher-standalone/package.json index 2bea36ec93..36df109d76 100644 --- a/packages/ketcher-standalone/package.json +++ b/packages/ketcher-standalone/package.json @@ -42,7 +42,7 @@ }, "dependencies": { "@babel/runtime": "^7.17.9", - "indigo-ketcher": "1.22.0-rc.3", + "indigo-ketcher": "1.23.0-dev.4", "ketcher-core": "*" }, "devDependencies": {