diff --git a/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts index 17e942e3ab..8495791e09 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts @@ -157,4 +157,72 @@ test.describe('Rectangle Selection Tool', () => { await page.mouse.click(betaAlaninePosition.x, betaAlaninePosition.y); await takeEditorScreenshot(page); }); + + test('Group selection using `Shift+LClick`', async ({ page }) => { + /* + Test case: #3728 - Group selection using Shift+LClick for Macromolecules editor + Description: Selection elements pointly + */ + + // Create 4 peptides on canvas + const MONOMER_NAME = 'Tza___3-thiazolylalanine'; + const MONOMER_ALIAS = 'Tza'; + + const peptide1 = await addMonomerToCanvas( + page, + MONOMER_NAME, + MONOMER_ALIAS, + 300, + 300, + 0, + ); + const peptide2 = await addMonomerToCanvas( + page, + MONOMER_NAME, + MONOMER_ALIAS, + 400, + 400, + 1, + ); + const peptide3 = await addMonomerToCanvas( + page, + MONOMER_NAME, + MONOMER_ALIAS, + 500, + 500, + 2, + ); + const peptide4 = await addMonomerToCanvas( + page, + MONOMER_NAME, + MONOMER_ALIAS, + 500, + 200, + 3, + ); + + // Select bond tool + await selectSingleBondTool(page); + + // Create bonds between peptides + await bondTwoMonomers(page, peptide1, peptide2); + await bondTwoMonomers(page, peptide3, peptide2); + await bondTwoMonomers(page, peptide3, peptide4); + + await takeEditorScreenshot(page); + + // Select rectangle selection tool + await selectRectangleSelectionTool(page); + + // Select monomers pointly by clicking Shift+LClick + await page.keyboard.down('Shift'); + + await page.mouse.click(300, 300); + await page.mouse.click(400, 400); + await page.mouse.click(500, 350); + + await page.keyboard.up('Shift'); + + await takeEditorScreenshot(page); + }); }); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-1-chromium-linux.png new file mode 100644 index 0000000000..73ce120816 Binary files /dev/null and b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-1-chromium-linux.png differ diff --git a/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-2-chromium-linux.png new file mode 100644 index 0000000000..ef0d3232e5 Binary files /dev/null and b/ketcher-autotests/tests/Macromolecule-editor/Rectangle-Selection-Tool/rectangle-selection-tool.spec.ts-snapshots/Rectangle-Selection-Tool-Group-selection-using-Shift-LClick-2-chromium-linux.png differ diff --git a/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts b/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts index c4134726ea..1897b4a59c 100644 --- a/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts +++ b/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts @@ -101,7 +101,7 @@ class SelectRectangle implements BaseTool { mousedown(event) { const renderer = event.target.__data__; let modelChanges: Command; - if (renderer instanceof BaseRenderer) { + if (renderer instanceof BaseRenderer && !event.shiftKey) { this.moveStarted = true; this.mousePositionAfterMove = this.editor.lastCursorPositionOfCanvas; this.mousePositionBeforeMove = this.editor.lastCursorPositionOfCanvas; @@ -112,6 +112,12 @@ class SelectRectangle implements BaseTool { renderer.drawingEntity, ); } + } else if (renderer instanceof BaseRenderer && event.shiftKey) { + const drawingEntity = renderer.drawingEntity; + modelChanges = + this.editor.drawingEntitiesManager.selectCurrentDrawingEntities( + drawingEntity, + ); } else { modelChanges = this.editor.drawingEntitiesManager.unselectAllDrawingEntities(); diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index c315e1e5a2..de7a0945f0 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -175,6 +175,29 @@ export class DrawingEntitiesManager { return command; } + public selectCurrentDrawingEntities(drawingEntity: DrawingEntity) { + const command = new Command(); + + this.allEntities.forEach(([, drawingEntity]) => { + if (drawingEntity.selected) { + const operation = new DrawingEntitySelectOperation(drawingEntity); + command.addOperation(operation); + } + }); + + if (drawingEntity.selected) { + drawingEntity.turnOffSelection(); + const operation = new DrawingEntitySelectOperation(drawingEntity); + command.addOperation(operation); + } else { + drawingEntity.turnOnSelection(); + const operation = new DrawingEntitySelectOperation(drawingEntity); + command.addOperation(operation); + } + + return command; + } + public moveDrawingEntityModelChange( drawingEntity: DrawingEntity, offset?: Vec2,