Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2367 - Ability to move items on the canvas #3286

Merged
merged 8 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { test } from '@playwright/test';
import {
addMonomerToCanvas,
dragMouseTo,
selectEraseTool,
selectRectangleArea,
selectRectangleSelectionTool,
selectSingleBondTool,
takeEditorScreenshot,
} from '@utils';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';
import { bondTwoMonomers } from '@utils/macromolecules/polymerBond';
Expand Down Expand Up @@ -69,4 +71,46 @@ test.describe('Rectangle Selection Tool', () => {
path: 'tests/Macromolecule-editor/screenshots/rectangle-selection-tool3.png',
});
});

test.skip('Move monomer bonded with another monomers', async ({ page }) => {
/*
Test case: #2367 - move items on the canvas
Description: check ability to move items on the canvas
*/

// Choose peptide
await page.getByText('Tza').click();

// Create 4 peptides on canvas
await page.mouse.click(300, 300);
await page.mouse.click(400, 400);
await page.mouse.click(500, 500);
await page.mouse.click(600, 600);

// Get 4 peptides locators
const peptides = await page.getByText('Tza').locator('..');
const peptide1 = peptides.nth(0);
const peptide2 = peptides.nth(1);
const peptide3 = peptides.nth(2);
const peptide4 = peptides.nth(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);

// Move selected monomer
await selectRectangleSelectionTool(page);
await page.mouse.move(400, 400);
await dragMouseTo(500, 500, page);
await page.mouse.move(400, 400);
await dragMouseTo(200, 400, page);

await takeEditorScreenshot(page);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
} from '../../../mock-data';
import { createPolymerEditorCanvas } from '../../../helpers/dom';
import { SelectRectangle } from 'application/editor/tools/SelectRectangle';
import { Vec2 } from 'domain/entities/vec2';
import { BaseMonomerRenderer } from 'application/render/renderers';

jest.mock('d3', () => {
return {
Expand Down Expand Up @@ -69,4 +71,44 @@ describe('Select Rectangle Tool', () => {
canvas.dispatchEvent(new Event('mouseover', { bubbles: true }));
expect(onShow).toHaveBeenCalled();
});

it('should move selected entity', () => {
const canvas: SVGSVGElement = createPolymerEditorCanvas();
const editor = new CoreEditor({
theme: polymerEditorTheme,
canvas,
});

const modelChanges = editor.drawingEntitiesManager.addMonomer(
peptideMonomerItem,
new Vec2(0, 0),
);
editor.renderersContainer.update(modelChanges);
const peptide = Array.from(editor.drawingEntitiesManager.monomers)[0][1];
const onMove = jest.fn();
jest
.spyOn(BaseMonomerRenderer.prototype, 'moveSelection')
.mockImplementation(onMove);

const selectRectangleTool = new SelectRectangle(editor);

const initialPosition = peptide.position;
const event = {
target: {
__data__: peptide.renderer,
},
pageX: initialPosition.x,
pageY: initialPosition.y,
};

editor.drawingEntitiesManager.selectDrawingEntity(peptide);
selectRectangleTool.mousedown(event);
editor.lastCursorPosition.x = initialPosition.x + 100;
editor.lastCursorPosition.y = initialPosition.y + 100;

selectRectangleTool.mousemove();
selectRectangleTool.mouseup(event);

expect(onMove).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ export class DrawingEntitySelectOperation implements Operation {
renderersManager.selectDrawingEntity(this.drawingEntity);
}
}
export class DrawingEntityMoveOperation implements Operation {
constructor(private drawingEntity: DrawingEntity) {}

public execute(renderersManager: RenderersManager) {
renderersManager.moveDrawingEntity(this.drawingEntity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { BaseTool } from 'application/editor/tools/Tool';
class SelectRectangle implements BaseTool {
private brush;
private brushArea;
private moveStarted;
private mousePositionAfterMove;

constructor(private editor: CoreEditor) {
this.editor = editor;
Expand Down Expand Up @@ -69,16 +71,49 @@ class SelectRectangle implements BaseTool {
const renderer = event.target.__data__;
let modelChanges: Command;
if (renderer instanceof BaseRenderer) {
modelChanges = this.editor.drawingEntitiesManager.selectDrawingEntity(
renderer.drawingEntity,
);
if (renderer.drawingEntity.selected) {
this.moveStarted = true;
this.mousePositionAfterMove = [
this.editor.lastCursorPosition.x,
this.editor.lastCursorPosition.y,
];
return;
} else {
modelChanges = this.editor.drawingEntitiesManager.selectDrawingEntity(
renderer.drawingEntity,
);
}
} else {
modelChanges =
this.editor.drawingEntitiesManager.unselectAllDrawingEntities();
}
this.editor.renderersContainer.update(modelChanges);
}

mousemove() {
if (this.moveStarted) {
const modelChanges =
this.editor.drawingEntitiesManager.moveSelectedDrawingEntities(
new Vec2(
this.editor.lastCursorPosition.x - this.mousePositionAfterMove[0],
this.editor.lastCursorPosition.y - this.mousePositionAfterMove[1],
),
);
this.mousePositionAfterMove = [
this.editor.lastCursorPosition.x,
this.editor.lastCursorPosition.y,
];
this.editor.renderersContainer.update(modelChanges);
}
}

mouseup(event) {
const renderer = event.target.__data__;
if (this.moveStarted && renderer.drawingEntity.selected) {
this.moveStarted = false;
}
}

mouseOverDrawingEntity(event) {
const renderer = event.target.__data__;
const modelChanges =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ export abstract class BaseMonomerRenderer extends BaseRenderer {
}
}

public moveSelection() {
assert(this.rootElement);
this.appendSelection();
this.move();
}

public move() {
this.rootElement?.attr(
'transform',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export abstract class BaseRenderer implements IBaseRenderer {

public abstract show(theme): void;
public abstract drawSelection(): void;
public abstract moveSelection(): void;
protected abstract appendHover(
hoverArea,
): D3SvgElementSelection<SVGUseElement, void> | void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export class PolymerBondRenderer extends BaseRenderer {
return this.rootBBox?.height || 0;
}

public moveSelection() {
assert(this.rootElement);
this.moveStart();
this.moveEnd();
}

public appendBond(rootElement) {
this.bodyElement = rootElement
.append('line')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export class RenderersManager {
drawingEntity.baseRenderer.drawSelection();
}

public moveDrawingEntity(drawingEntity: DrawingEntity) {
assert(drawingEntity.baseRenderer);
drawingEntity.baseRenderer.moveSelection();
}

public addMonomer(monomer: BaseMonomer, callback?: () => void) {
const [, MonomerRenderer] = monomerFactory(monomer.monomerItem);
const monomerRenderer = new MonomerRenderer(monomer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import {
DrawingEntityHoverOperation,
DrawingEntitySelectOperation,
DrawingEntityMoveOperation,
} from 'application/editor/operations/drawingEntity';
import {
PolymerBondAddOperation,
Expand Down Expand Up @@ -116,6 +117,38 @@ export class DrawingEntitiesManager {
return command;
}

public moveSelectedDrawingEntities(offset: Vec2) {
const command = new Command();

this.monomers.forEach((drawingEntity) => {
if (drawingEntity.selected) {
drawingEntity.moveRelative(offset);
command.merge(this.createDrawingEntityMovingCommand(drawingEntity));
}
});

this.polymerBonds.forEach((drawingEntity) => {
if (
drawingEntity.selected ||
drawingEntity.firstMonomer.selected ||
drawingEntity.secondMonomer?.selected
) {
drawingEntity.moveToLinkedMonomers();
command.merge(this.createDrawingEntityMovingCommand(drawingEntity));
}
});
return command;
}

public createDrawingEntityMovingCommand(drawingEntity: DrawingEntity) {
const command = new Command();

const movingCommand = new DrawingEntityMoveOperation(drawingEntity);
command.addOperation(movingCommand);

return command;
}

public deleteMonomer(monomer: BaseMonomer) {
this.monomers.delete(monomer.id);
const command = new Command();
Expand Down Expand Up @@ -402,6 +435,7 @@ export class DrawingEntitiesManager {
let monomerAddOperation;
if (previousMonomer) {
const polymerBond = new PolymerBond(previousMonomer);
this.polymerBonds.set(polymerBond.id, polymerBond);
monomerAddOperation = new MonomerAddOperation(monomer, () => {
polymerBond.moveToLinkedMonomers();
});
Expand Down
Loading