Support for client offset in scrolled area

This commit is contained in:
Piotr Pekala 2019-02-25 01:42:39 -08:00
parent f553c7a200
commit c063620cbf
13 changed files with 92 additions and 34 deletions

View File

@ -25,8 +25,8 @@ export class DrawingAddingComponent implements OnInit, OnDestroy {
activate() {
let listener = (event: MouseEvent) => {
let x = event.clientX - this.context.getZeroZeroTransformationPoint().x;
let y = event.clientY - this.context.getZeroZeroTransformationPoint().y;
let x = event.pageX - this.context.getZeroZeroTransformationPoint().x;
let y = event.pageY - this.context.getZeroZeroTransformationPoint().y;
this.drawingsEventSource.pointToAddSelected.emit(new AddedDataEvent(x, y));
this.deactivate();

View File

@ -45,8 +45,8 @@ export class TextEditorComponent implements OnInit, OnDestroy {
activateTextAdding() {
let addTextListener = (event: MouseEvent) => {
this.leftPosition = event.clientX.toString() + 'px';
this.topPosition = (event.clientY + window.pageYOffset).toString() + 'px';
this.leftPosition = event.pageX.toString() + 'px';
this.topPosition = event.pageY.toString() + 'px';
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
this.temporaryTextElement.nativeElement.focus();
@ -54,8 +54,8 @@ export class TextEditorComponent implements OnInit, OnDestroy {
this.drawingsEventSource.textAdded.emit(
new TextAddedDataEvent(
this.temporaryTextElement.nativeElement.innerText.replace(/\n$/, ''),
event.clientX,
event.clientY
event.pageX,
event.pageY
)
);
this.deactivateTextAdding();

View File

@ -111,15 +111,15 @@ export class DrawingsWidget implements Widget {
}
}
} else {
dy = y - (evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y);
y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
dy = y - (evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y);
y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y;
if (datum.element.height + dy < 0) {
isReflectedVertical = false;
y = topEdge;
datum.element.height = Math.abs(datum.element.height + evt.dy);
} else {
datum.y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
datum.y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y;
datum.element.height += dy;
if (datum.element instanceof EllipseElement) {
(datum.element as EllipseElement).cy =
@ -143,7 +143,7 @@ export class DrawingsWidget implements Widget {
let top = drag()
.on('start', (datum: MapDrawing) => {
y = event.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
y = event.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y;
bottomEdge = y + datum.element.height;
document.body.style.cursor = 'ns-resize';
})
@ -151,15 +151,15 @@ export class DrawingsWidget implements Widget {
const evt = event;
if (!isReflectedVertical) {
dy = y - (evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y);
y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
dy = y - (evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y);
y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y;
if (datum.element.height + dy < 0) {
y = bottomEdge;
isReflectedVertical = true;
datum.element.height = Math.abs(datum.element.height + evt.dy);
} else {
datum.y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
datum.y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y;
datum.element.height += dy;
if (datum.element instanceof EllipseElement) {
(datum.element as EllipseElement).cy =
@ -207,7 +207,7 @@ export class DrawingsWidget implements Widget {
let isReflectedHorizontal: boolean = false;
let right = drag()
.on('start', (datum: MapDrawing) => {
x = event.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x;
x = event.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x;
leftEdge = x + datum.element.width;
document.body.style.cursor = 'ew-resize';
})
@ -215,15 +215,15 @@ export class DrawingsWidget implements Widget {
const evt = event;
if (!isReflectedHorizontal) {
dx = x - (evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x);
x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x;
dx = x - (evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x);
x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x;
if (datum.element.width + dx < 0) {
x = leftEdge;
isReflectedHorizontal = true;
datum.element.width = Math.abs(datum.element.width + evt.dx);
} else {
datum.x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x;
datum.x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x;
datum.element.width += dx;
if (datum.element instanceof EllipseElement) {
(datum.element as EllipseElement).cx =
@ -290,15 +290,15 @@ export class DrawingsWidget implements Widget {
datum.element.width = datum.element.width + evt.dx < 0 ? 1 : (datum.element.width += evt.dx);
}
} else {
dx = x - (evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x);
x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x;
dx = x - (evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x);
x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x;
if (datum.element.width + dx < 0) {
x = rightEdge;
isReflectedHorizontal = false;
datum.element.width = Math.abs(datum.element.width + evt.dx);
} else {
datum.x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x;
datum.x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x;
datum.element.width += dx;
if (datum.element instanceof EllipseElement) {
(datum.element as EllipseElement).cx =

View File

@ -6,6 +6,9 @@ import { NodeService } from '../../../../../services/node.service';
import { Drawing } from '../../../../../cartography/models/drawing';
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
import { DrawingService } from '../../../../../services/drawing.service';
import { Link } from '../../../../../models/link';
import { LinkService } from '../../../../../services/link.service';
import { LinksDataSource } from '../../../../../cartography/datasources/links-datasource';
@Component({
selector: 'app-delete-action',
@ -15,12 +18,15 @@ export class DeleteActionComponent implements OnInit {
@Input() server: Server;
@Input() nodes: Node[];
@Input() drawings: Drawing[];
@Input() links: Link[];
constructor(
private nodesDataSource: NodesDataSource,
private drawingsDataSource: DrawingsDataSource,
private linksDataSource: LinksDataSource,
private nodeService: NodeService,
private drawingService: DrawingService
private drawingService: DrawingService,
private linkService: LinkService
) {}
ngOnInit() {}
@ -37,5 +43,11 @@ export class DeleteActionComponent implements OnInit {
this.drawingService.delete(this.server, drawing).subscribe((drawing: Drawing) => {});
});
this.links.forEach((link) => {
this.linksDataSource.remove(link);
this.linkService.deleteLink(this.server, link).subscribe(() => {});
});
}
}

View File

@ -15,13 +15,13 @@
[drawing]="drawings[0]"
></app-edit-text-action>
<app-move-layer-up-action
*ngIf="!projectService.isReadOnly(project)"
*ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)"
[server]="server"
[nodes]="nodes"
[drawings]="drawings"
></app-move-layer-up-action>
<app-move-layer-down-action
*ngIf="!projectService.isReadOnly(project)"
*ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)"
[server]="server"
[nodes]="nodes"
[drawings]="drawings"
@ -31,6 +31,7 @@
[server]="server"
[nodes]="nodes"
[drawings]="drawings"
[links]="links"
></app-delete-action>
</mat-menu>
</div>

View File

@ -8,6 +8,7 @@ import { ProjectService } from '../../../services/project.service';
import { Drawing } from '../../../cartography/models/drawing';
import { TextElement } from '../../../cartography/models/drawings/text-element';
import { Label } from '../../../cartography/models/label';
import { Link } from '../../../models/link';
@Component({
@ -27,6 +28,7 @@ export class ContextMenuComponent implements OnInit {
drawings: Drawing[] = [];
nodes: Node[] = [];
labels: Label[] = [];
links: Link[] = [];
hasTextCapabilities: boolean = false;
@ -74,12 +76,13 @@ export class ContextMenuComponent implements OnInit {
this.contextMenu.openMenu();
}
public openMenuForListOfElements(drawings: Drawing[], nodes: Node[], labels: Label[], top: number, left: number) {
public openMenuForListOfElements(drawings: Drawing[], nodes: Node[], labels: Label[], links: Link[], top: number, left: number) {
this.resetCapabilities();
this.drawings = drawings;
this.nodes = nodes;
this.labels = labels;
this.links = links;
this.setPosition(top, left);
this.contextMenu.openMenu();

View File

@ -1 +1 @@
<app-node-select-interface (onChooseInterface)="onChooseInterface($event)"></app-node-select-interface>
<app-node-select-interface [links]="links" (onChooseInterface)="onChooseInterface($event)"></app-node-select-interface>

View File

@ -1,4 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Component, OnInit, OnDestroy, ViewChild, Input } from '@angular/core';
import { Subscription } from 'rxjs';
import { NodeSelectInterfaceComponent } from '../../../components/project-map/node-select-interface/node-select-interface.component';
import { DrawingLineWidget } from '../../../cartography/widgets/drawing-line';
@ -7,6 +7,8 @@ import { LinksEventSource } from '../../../cartography/events/links-event-source
import { MapNode } from '../../../cartography/models/map/map-node';
import { MapPort } from '../../../cartography/models/map/map-port';
import { MapLinkCreated } from '../../../cartography/events/links';
import { Link } from '../../../models/link';
import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter';
@Component({
selector: 'app-draw-link-tool',
@ -14,6 +16,7 @@ import { MapLinkCreated } from '../../../cartography/events/links';
styleUrls: ['./draw-link-tool.component.scss']
})
export class DrawLinkToolComponent implements OnInit, OnDestroy {
@Input() links: Link[];
@ViewChild(NodeSelectInterfaceComponent) nodeSelectInterfaceMenu: NodeSelectInterfaceComponent;
private nodeClicked$: Subscription;
@ -21,12 +24,14 @@ export class DrawLinkToolComponent implements OnInit, OnDestroy {
constructor(
private drawingLineTool: DrawingLineWidget,
private nodesEventSource: NodesEventSource,
private linksEventSource: LinksEventSource
private linksEventSource: LinksEventSource,
private mapNodeToNode: MapNodeToNodeConverter
) {}
ngOnInit() {
this.nodeClicked$ = this.nodesEventSource.clicked.subscribe(clickedEvent => {
this.nodeSelectInterfaceMenu.open(clickedEvent.datum, clickedEvent.y, clickedEvent.x);
let node = this.mapNodeToNode.convert(clickedEvent.datum);
this.nodeSelectInterfaceMenu.open(node, clickedEvent.y, clickedEvent.x);
});
}

View File

@ -1,7 +1,7 @@
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node">
<span [matMenuTriggerFor]="selectInterfaceMenu"></span>
<mat-menu #selectInterfaceMenu="matMenu" class="context-menu-items">
<button mat-menu-item *ngFor="let port of node.ports" (click)="chooseInterface(port)">
<button mat-menu-item *ngFor="let port of availablePorts" (click)="chooseInterface(port)">
<mat-icon>add_circle_outline</mat-icon>
<span>{{ port.name }}</span>
</button>

View File

@ -3,6 +3,8 @@ import { MatMenuTrigger } from '@angular/material';
import { DomSanitizer } from '@angular/platform-browser';
import { Node } from '../../../cartography/models/node';
import { Port } from '../../../models/port';
import { Link } from '../../../models/link';
import { LinkNode } from '../../../models/link-node';
@Component({
selector: 'app-node-select-interface',
@ -10,6 +12,7 @@ import { Port } from '../../../models/port';
styleUrls: ['./node-select-interface.component.scss']
})
export class NodeSelectInterfaceComponent implements OnInit {
@Input() links: Link[];
@Output() onChooseInterface = new EventEmitter<any>();
@ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger;
@ -17,8 +20,12 @@ export class NodeSelectInterfaceComponent implements OnInit {
protected topPosition;
protected leftPosition;
public node: Node;
public availablePorts: Port[];
constructor(private sanitizer: DomSanitizer, private changeDetector: ChangeDetectorRef) {}
constructor(
private sanitizer: DomSanitizer,
private changeDetector: ChangeDetectorRef
) {}
ngOnInit() {
this.setPosition(0, 0);
@ -32,10 +39,29 @@ export class NodeSelectInterfaceComponent implements OnInit {
public open(node: Node, top: number, left: number) {
this.node = node;
this.filterNodePorts();
this.setPosition(top, left);
this.contextMenu.openMenu();
}
public filterNodePorts() {
let linkNodes: LinkNode[] = [];
this.links.forEach((link: Link) => {
link.nodes.forEach((linkNode: LinkNode) => {
if(linkNode.node_id === this.node.node_id) {
linkNodes.push(linkNode);
}
});
});
this.availablePorts = [];
this.node.ports.forEach((port: Port) => {
if(linkNodes.filter((linkNode: LinkNode) => linkNode.port_number === port.port_number).length === 0){
this.availablePorts.push(port);
}
});
}
public chooseInterface(port: Port) {
this.onChooseInterface.emit({
node: this.node,

View File

@ -141,7 +141,7 @@
<app-project-map-shortcuts *ngIf="project" [project]="project" [server]="server"> </app-project-map-shortcuts>
<app-draw-link-tool *ngIf="tools.draw_link"></app-draw-link-tool>
<app-draw-link-tool [links]="links" *ngIf="tools.draw_link"></app-draw-link-tool>
<app-drawing-added
[server]="server"

View File

@ -40,6 +40,8 @@ import { Label } from '../../cartography/models/label';
import { MapNode } from '../../cartography/models/map/map-node';
import { MapLabelToLabelConverter } from '../../cartography/converters/map/map-label-to-label-converter';
import { RecentlyOpenedProjectService } from '../../services/recentlyOpenedProject.service';
import { MapLink } from '../../cartography/models/map/map-link';
import { MapLinkToLinkConverter } from '../../cartography/converters/map/map-link-to-link-converter';
@Component({
@ -96,6 +98,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
private mapNodeToNode: MapNodeToNodeConverter,
private mapDrawingToDrawing: MapDrawingToDrawingConverter,
private mapLabelToLabel: MapLabelToLabelConverter,
private mapLinkToLink: MapLinkToLinkConverter,
private nodesDataSource: NodesDataSource,
private linksDataSource: LinksDataSource,
private drawingsDataSource: DrawingsDataSource,
@ -218,12 +221,12 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
const onNodeContextMenu = this.nodeWidget.onContextMenu.subscribe((eventNode: NodeContextMenu) => {
const node = this.mapNodeToNode.convert(eventNode.node);
this.contextMenu.openMenuForNode(node, eventNode.event.clientY, eventNode.event.clientX);
this.contextMenu.openMenuForNode(node, eventNode.event.pageY, eventNode.event.pageX);
});
const onDrawingContextMenu = this.drawingsWidget.onContextMenu.subscribe((eventDrawing: DrawingContextMenu) => {
const drawing = this.mapDrawingToDrawing.convert(eventDrawing.drawing);
this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.clientY, eventDrawing.event.clientX);
this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.pageY, eventDrawing.event.pageX);
});
const onContextMenu = this.selectionTool.contextMenuOpened.subscribe((event) => {
@ -233,6 +236,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
let drawings: Drawing[] = [];
let nodes: Node[] = [];
let labels: Label[] = [];
let links: Link[] = [];
selectedItems.forEach((elem) => {
if (elem instanceof MapDrawing) {
@ -241,10 +245,12 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
nodes.push(this.mapNodeToNode.convert(elem));
} else if (elem instanceof MapLabel) {
labels.push(this.mapLabelToLabel.convert(elem));
} else if (elem instanceof MapLink) {
links.push(this.mapLinkToLink.convert(elem))
}
});
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, event.clientY, event.clientX);
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX);
});
this.subscriptions.push(onNodeContextMenu);

View File

@ -12,6 +12,11 @@ import { LinkNode } from '../models/link-node';
export class LinkService {
constructor(private httpServer: HttpServer) {}
deleteLink(server: Server, link: Link) {
//return this.httpServer.delete(server, `/compute/projects/${link.project_id}/vpcs/nodes/${link.nodes[0].node_id}/adapters/0/ports/0/nio`)
return this.httpServer.delete(server, `/projects/${link.project_id}/links/${link.link_id}`)
}
createLink(server: Server, source_node: Node, source_port: Port, target_node: Node, target_port: Port) {
return this.httpServer.post(server, `/projects/${source_node.project_id}/links`, {
nodes: [