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

260 feature request align selected nodes all at once #389

Merged
merged 5 commits into from
Dec 17, 2024
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
27 changes: 16 additions & 11 deletions documentation/AdvancedEditingShortcuts.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,23 @@ easier to manage and edit complex network structures.

### Short-cuts

| Keyboard | description |
|:----------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| | |
| `delete` | Delete nodes, comments, and selected trainruns. |
| `ctrl`+`d` / `insert` | Duplicate nodes, comments, and selected trainruns (if multiple nodes are selected, trains including nodes will be duplicated). |
| `insert` | Add new nodes under the mouse on the drawing area. |
| `escape` | Select trainruns / In multi-node move mode, all selected nodes will be unselected. |
| Keyboard | description |
|:----------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| | |
| `delete` | Delete nodes, comments, and selected trainruns. |
| `ctrl`+`d` / `insert` | Duplicate nodes, comments, and selected trainruns (if multiple nodes are selected, trains including nodes will be duplicated). |
| `insert` | Add new nodes under the mouse on the drawing area. |
| `escape` | Select trainruns / In multi-node move mode, all selected nodes will be unselected. |
| `shift` + `left mouse button` pressed and move (or alternatively with the `right mouse button` pressed and move) | Multi-select nodes and notes for subsequent moving or delete all selected elements by using `Delete`. |
| `ctrl`+`z` | Undo - Reverse the previous action. |
| `ctrl`+`c` | Copy the currently visible trainruns. The copied content remains in the browser's memory/cache and can be pasted into different variants (even after closing the browser, the data remains saved). |
| `ctrl`+`v` | Paste the copied trainruns. |
| `ctrl`+`a` | Select all. |
| `ctrl`+`z` | Undo - Reverse the previous action. |
| `ctrl`+`c` | Copy the currently visible trainruns. The copied content remains in the browser's memory/cache and can be pasted into different variants (even after closing the browser, the data remains saved). |
| `ctrl`+`v` | Paste the copied trainruns. |
| `ctrl`+`a` | Select all. |
| | |
| `Arrow left` | Align all selected nodes - left. |
| `Arrow up` | Align all selected nodes - top. |
| `Arrow right` | Align all selected nodes - right. |
| `Arrow down` | Align all selected nodes - bottom. |
---

### Scale Netzgrafik
Expand Down
197 changes: 197 additions & 0 deletions src/app/services/util/position.transformation.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import {DataService} from "../../services/data/data.service";
import {NodeService} from "../../services/data/node.service";
import {ResourceService} from "../../services/data/resource.service";
import {TrainrunService} from "../../services/data/trainrun.service";
import {TrainrunSectionService} from "../../services/data/trainrunsection.service";
import {StammdatenService} from "../../services/data/stammdaten.service";
import {NoteService} from "../../services/data/note.service";
import {Node} from "../../models/node.model";
import {TrainrunSection} from "../../models/trainrunsection.model";
import {LabelGroupService} from "../../services/data/labelgroup.service";
import {LabelService} from "../../services/data/label.serivce";
import {NetzgrafikColoringService} from "../../services/data/netzgrafikColoring.service";
import {LogService} from "../../logger/log.service";
import {LogPublishersService} from "../../logger/log.publishers.service";
import {FilterService} from "../../services/ui/filter.service";
import {UiInteractionService} from "../../services/ui/ui.interaction.service";
import {LoadPerlenketteService} from "../../perlenkette/service/load-perlenkette.service";
import {NetzgrafikUnitTesting} from "../../../integration-testing/netzgrafik.unit.testing";
import {ViewportCullService} from "../../services/ui/viewport.cull.service";
import {PositionTransformationService} from "./position.transformation.service";
import {Vec2D} from "../../utils/vec2D";

describe("PositionTransformationService", () => {
let dataService: DataService;
let nodeService: NodeService;
let resourceService: ResourceService;
let trainrunService: TrainrunService;
let trainrunSectionService: TrainrunSectionService;
let stammdatenService: StammdatenService;
let noteService: NoteService;
let nodes: Node[] = null;
let trainrunSections: TrainrunSection[] = null;
let logService: LogService = null;
let logPublishersService: LogPublishersService = null;
let labelGroupService: LabelGroupService = null;
let labelService: LabelService = null;
let filterService: FilterService = null;
let netzgrafikColoringService: NetzgrafikColoringService = null;
let uiInteractionService: UiInteractionService = null;
let loadPerlenketteService: LoadPerlenketteService = null;
let positionTransformationService: PositionTransformationService = null;

beforeEach(() => {
stammdatenService = new StammdatenService();
resourceService = new ResourceService();
logPublishersService = new LogPublishersService();
logService = new LogService(logPublishersService);
labelGroupService = new LabelGroupService(logService);
labelService = new LabelService(logService, labelGroupService);
filterService = new FilterService(labelService, labelGroupService);
trainrunService = new TrainrunService(
logService,
labelService,
filterService,
);
trainrunSectionService = new TrainrunSectionService(
logService,
trainrunService,
filterService,
);
nodeService = new NodeService(
logService,
resourceService,
trainrunService,
trainrunSectionService,
labelService,
filterService,
);
noteService = new NoteService(logService, labelService, filterService);
netzgrafikColoringService = new NetzgrafikColoringService(logService);
dataService = new DataService(
resourceService,
nodeService,
trainrunSectionService,
trainrunService,
stammdatenService,
noteService,
labelService,
labelGroupService,
filterService,
netzgrafikColoringService,
);
nodeService.nodes.subscribe((updatesNodes) => (nodes = updatesNodes));
trainrunSectionService.trainrunSections.subscribe(
(updatesTrainrunSections) => (trainrunSections = updatesTrainrunSections),
);

loadPerlenketteService = new LoadPerlenketteService(
trainrunService,
trainrunSectionService,
nodeService,
filterService
);

uiInteractionService = new UiInteractionService(
filterService,
nodeService,
noteService,
stammdatenService,
trainrunSectionService,
trainrunService,
netzgrafikColoringService,
loadPerlenketteService,
);

const viewportCullSerivce = new ViewportCullService(
uiInteractionService,
nodeService,
noteService,
trainrunSectionService
);

positionTransformationService = new PositionTransformationService(
trainrunSectionService,
nodeService,
noteService,
uiInteractionService,
viewportCullSerivce
);
});

it("PositionTransformationService test-001", () => {
dataService.loadNetzgrafikDto(
NetzgrafikUnitTesting.getUnitTestNetzgrafik(),
);
const pos: Vec2D[] = [];
nodeService.getNodes().forEach((n) => {
pos.push(new Vec2D(n.getPositionX(), n.getPositionY()));
});
// no node is selected (default) - nothing changes
positionTransformationService.alignSelectedElementsToRightBorder();
positionTransformationService.alignSelectedElementsToLeftBorder();
positionTransformationService.alignSelectedElementsToTopBorder();
positionTransformationService.alignSelectedElementsToBottomBorder();
nodeService.getNodes().forEach((n: Node, index: number) => {
expect(n.getPositionX()).toBe(pos[index].getX());
expect(n.getPositionY()).toBe(pos[index].getY());
});
});

it("PositionTransformationService test-001", () => {
dataService.loadNetzgrafikDto(
NetzgrafikUnitTesting.getUnitTestNetzgrafik(),
);
const pos: Vec2D[] = [];
let minX = 100000;
nodeService.getNodes().forEach((n) => {
pos.push(new Vec2D(n.getPositionX(), n.getPositionY()));
nodeService.selectNode(n.getId());
minX = Math.min(n.getPositionX(), minX);
});
// all node are selected (default) - nothing changes
positionTransformationService.alignSelectedElementsToLeftBorder();
nodeService.getNodes().forEach((n: Node, index: number) => {
expect(n.getPositionX()).toBe(minX);
expect(n.getPositionY()).toBe(pos[index].getY());
});
});

it("PositionTransformationService test-002", () => {
dataService.loadNetzgrafikDto(
NetzgrafikUnitTesting.getUnitTestNetzgrafik(),
);
const pos: Vec2D[] = [];
let minY = 100000;
nodeService.getNodes().forEach((n) => {
pos.push(new Vec2D(n.getPositionX(), n.getPositionY()));
nodeService.selectNode(n.getId());
minY = Math.min(n.getPositionY(), minY);
});
// all node are selected (default) - nothing changes
positionTransformationService.alignSelectedElementsToTopBorder();
nodeService.getNodes().forEach((n: Node, index: number) => {
expect(n.getPositionX()).toBe(pos[index].getX());
expect(n.getPositionY()).toBe(minY);
});
});

it("PositionTransformationService test-003", () => {
dataService.loadNetzgrafikDto(
NetzgrafikUnitTesting.getUnitTestNetzgrafik(),
);
const pos: Vec2D[] = [];
nodeService.getNodes().forEach((n) => {
pos.push(new Vec2D(n.getPositionX(), n.getPositionY()));
});
// all node are selected (default) - nothing changes
positionTransformationService.scaleNetzgrafikArea(2.0,
new Vec2D(0.0, 0.0),
"graphContainer");
nodeService.getNodes().forEach((n: Node, index: number) => {
expect(n.getPositionX()).toBe(pos[index].getX() * 2.0);
expect(n.getPositionY()).toBe(pos[index].getY() * 2.0);
});
});

});
Loading
Loading