mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-23 14:52:22 +00:00
Basic implementation of context menu for drawings
This commit is contained in:
parent
9b9c0cdf4d
commit
b39cf7033f
@ -36,9 +36,9 @@ import { AppComponent } from './app.component';
|
||||
|
||||
import { ProjectMapComponent } from './components/project-map/project-map.component';
|
||||
import { ServersComponent, AddServerDialogComponent } from './components/servers/servers.component';
|
||||
import { NodeContextMenuComponent } from './components/project-map/node-context-menu/node-context-menu.component';
|
||||
import { StartNodeActionComponent } from './components/project-map/node-context-menu/actions/start-node-action/start-node-action.component';
|
||||
import { StopNodeActionComponent } from './components/project-map/node-context-menu/actions/stop-node-action/stop-node-action.component';
|
||||
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
||||
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
|
||||
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
||||
import { TemplateComponent } from './components/template/template.component';
|
||||
import { TemplateListDialogComponent } from './components/template/template-list-dialog/template-list-dialog.component';
|
||||
import { CartographyModule } from './cartography/cartography.module';
|
||||
@ -50,8 +50,9 @@ import { SymbolsDataSource } from "./cartography/datasources/symbols-datasource"
|
||||
import { SelectionManager } from "./cartography/managers/selection-manager";
|
||||
import { InRectangleHelper } from "./cartography/helpers/in-rectangle-helper";
|
||||
import { DrawingsDataSource } from "./cartography/datasources/drawings-datasource";
|
||||
import { MoveLayerDownActionComponent } from './components/project-map/node-context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
||||
import { MoveLayerUpActionComponent } from './components/project-map/node-context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
||||
import { EditStyleActionComponent } from './components/project-map/context-menu/actions/edit-style-action/edit-style-action.component';
|
||||
import { MoveLayerDownActionComponent } from './components/project-map/context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
||||
import { MoveLayerUpActionComponent } from './components/project-map/context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
||||
import { ProjectMapShortcutsComponent } from './components/project-map/project-map-shortcuts/project-map-shortcuts.component';
|
||||
import { SettingsComponent } from './components/settings/settings.component';
|
||||
import { SettingsService } from "./services/settings.service";
|
||||
@ -113,13 +114,14 @@ if (environment.production) {
|
||||
ConfirmationDialogComponent,
|
||||
DefaultLayoutComponent,
|
||||
ProgressDialogComponent,
|
||||
NodeContextMenuComponent,
|
||||
ContextMenuComponent,
|
||||
StartNodeActionComponent,
|
||||
StopNodeActionComponent,
|
||||
TemplateComponent,
|
||||
TemplateListDialogComponent,
|
||||
MoveLayerDownActionComponent,
|
||||
MoveLayerUpActionComponent,
|
||||
EditStyleActionComponent,
|
||||
ProjectMapShortcutsComponent,
|
||||
SettingsComponent,
|
||||
LocalServerComponent,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TextElement } from '../models/drawings/text-element';
|
||||
import { MapDrawing } from '../models/map/map-drawing';
|
||||
|
||||
export class DataEventSource<T> {
|
||||
constructor(
|
||||
@ -50,3 +51,10 @@ export class TextEditedDataEvent {
|
||||
public textElement: TextElement
|
||||
) {}
|
||||
}
|
||||
|
||||
export class DrawingContextMenu {
|
||||
constructor(
|
||||
public event: any,
|
||||
public drawing: MapDrawing
|
||||
) {}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import { EllipseElement } from "../models/drawings/ellipse-element";
|
||||
import { ResizingEnd } from "../events/resizing";
|
||||
import { LineElement } from "../models/drawings/line-element";
|
||||
import { MapSettingsManager } from "../managers/map-settings-manager";
|
||||
import { DrawingContextMenu } from '../events/event-source';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@ -21,6 +22,7 @@ export class DrawingsWidget implements Widget {
|
||||
public draggable = new Draggable<SVGGElement, MapDrawing>();
|
||||
public draggingEnabled = false;
|
||||
public resizingFinished = new EventEmitter<ResizingEnd<MapDrawing>>();
|
||||
public onContextMenu = new EventEmitter<DrawingContextMenu>();
|
||||
|
||||
// public onContextMenu = new EventEmitter<NodeContextMenu>();
|
||||
// public onDrawingClicked = new EventEmitter<NodeClicked>();
|
||||
@ -60,6 +62,10 @@ export class DrawingsWidget implements Widget {
|
||||
.append<SVGGElement>('g')
|
||||
.attr('class', 'drawing')
|
||||
.attr('drawing_id', (l: MapDrawing) => l.id)
|
||||
.on('contextmenu', (l: MapDrawing) => {
|
||||
event.preventDefault();
|
||||
this.onContextMenu.emit(new DrawingContextMenu(event, l));
|
||||
})
|
||||
|
||||
const merge = drawing.merge(drawing_enter);
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
<button mat-menu-item (click)="editStyle()">
|
||||
<mat-icon>style</mat-icon>
|
||||
<span>Edit style</span>
|
||||
</button>
|
@ -0,0 +1,24 @@
|
||||
import { Component, OnInit, Input } from "@angular/core";
|
||||
import { Drawing } from '../../../../../cartography/models/drawing';
|
||||
import { Server } from '../../../../../models/server';
|
||||
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
|
||||
import { DrawingService } from '../../../../../services/drawing.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-style-action',
|
||||
templateUrl: './edit-style-action.component.html'
|
||||
})
|
||||
export class EditStyleActionComponent implements OnInit {
|
||||
@Input() server: Server;
|
||||
@Input() drawing: Drawing;
|
||||
|
||||
constructor(
|
||||
private drawingsDataSource: DrawingsDataSource,
|
||||
private drawingService: DrawingService
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
editStyle(){}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Server } from '../../../../../models/server';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-move-layer-down-action',
|
||||
templateUrl: './move-layer-down-action.component.html'
|
||||
})
|
||||
export class MoveLayerDownActionComponent implements OnInit {
|
||||
@Input() server: Server;
|
||||
@Input() node: Node;
|
||||
@Input() drawing: Drawing;
|
||||
|
||||
constructor(
|
||||
private nodesDataSource: NodesDataSource,
|
||||
private drawingsDataSource: DrawingsDataSource,
|
||||
private nodeService: NodeService,
|
||||
private drawingService: DrawingService
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
moveLayerDown() {
|
||||
if (this.node) {
|
||||
this.node.z--;
|
||||
this.nodesDataSource.update(this.node);
|
||||
|
||||
this.nodeService
|
||||
.update(this.server, this.node)
|
||||
.subscribe((node: Node) => {});
|
||||
} else if(this.drawing) {
|
||||
this.drawing.z--;
|
||||
this.drawingsDataSource.update(this.drawing);
|
||||
|
||||
this.drawingService
|
||||
.update(this.server, this.drawing)
|
||||
.subscribe((drawing: Drawing) => {});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Server } from '../../../../../models/server';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-move-layer-up-action',
|
||||
templateUrl: './move-layer-up-action.component.html'
|
||||
})
|
||||
export class MoveLayerUpActionComponent implements OnInit {
|
||||
@Input() server: Server;
|
||||
@Input() node: Node;
|
||||
@Input() drawing: Drawing;
|
||||
|
||||
constructor(
|
||||
private nodesDataSource: NodesDataSource,
|
||||
private drawingsDataSource: DrawingsDataSource,
|
||||
private nodeService: NodeService,
|
||||
private drawingService: DrawingService
|
||||
) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
moveLayerUp() {
|
||||
if (this.node) {
|
||||
this.node.z++;
|
||||
this.nodesDataSource.update(this.node);
|
||||
|
||||
this.nodeService
|
||||
.update(this.server, this.node)
|
||||
.subscribe((node: Node) => {});
|
||||
} else if(this.drawing) {
|
||||
this.drawing.z++;
|
||||
this.drawingsDataSource.update(this.drawing);
|
||||
|
||||
this.drawingService
|
||||
.update(this.server, this.drawing)
|
||||
.subscribe((drawing: Drawing) => {});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node || drawing">
|
||||
<span [matMenuTriggerFor]="contextMenu"></span>
|
||||
<mat-menu #contextMenu="matMenu" class="context-menu-items">
|
||||
<app-start-node-action *ngIf="hasNodeCapabilities" [server]="server" [node]="node"></app-start-node-action>
|
||||
<app-stop-node-action *ngIf="hasNodeCapabilities" [server]="server" [node]="node"></app-stop-node-action>
|
||||
<app-edit-style-action *ngIf="hasDrawingCapabilities" [server]="server" [drawing]="drawing"></app-edit-style-action>
|
||||
<app-move-layer-up-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node" [drawing]="drawing"></app-move-layer-up-action>
|
||||
<app-move-layer-down-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node" [drawing]="drawing"></app-move-layer-down-action>
|
||||
</mat-menu>
|
||||
</div>
|
@ -1,20 +1,20 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NodeContextMenuComponent } from './node-context-menu.component';
|
||||
import { ContextMenuComponent } from './context-menu.component';
|
||||
|
||||
describe('NodeContextMenuComponent', () => {
|
||||
let component: NodeContextMenuComponent;
|
||||
let fixture: ComponentFixture<NodeContextMenuComponent>;
|
||||
let component: ContextMenuComponent;
|
||||
let fixture: ComponentFixture<ContextMenuComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NodeContextMenuComponent ]
|
||||
declarations: [ ContextMenuComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NodeContextMenuComponent);
|
||||
fixture = TestBed.createComponent(ContextMenuComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
@ -5,14 +5,15 @@ import { Node } from "../../../cartography/models/node";
|
||||
import { Server } from "../../../models/server";
|
||||
import { Project } from "../../../models/project";
|
||||
import { ProjectService } from "../../../services/project.service";
|
||||
import { Drawing } from '../../../cartography/models/drawing';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-node-context-menu',
|
||||
templateUrl: './node-context-menu.component.html',
|
||||
styleUrls: ['./node-context-menu.component.scss']
|
||||
selector: 'app-context-menu',
|
||||
templateUrl: './context-menu.component.html',
|
||||
styleUrls: ['./context-menu.component.scss']
|
||||
})
|
||||
export class NodeContextMenuComponent implements OnInit {
|
||||
export class ContextMenuComponent implements OnInit {
|
||||
@Input() project: Project;
|
||||
@Input() server: Server;
|
||||
|
||||
@ -21,6 +22,9 @@ export class NodeContextMenuComponent implements OnInit {
|
||||
topPosition;
|
||||
leftPosition;
|
||||
node: Node;
|
||||
drawing: Drawing;
|
||||
private hasNodeCapabilities: boolean = false;
|
||||
private hasDrawingCapabilities: boolean = false;
|
||||
|
||||
constructor(
|
||||
private sanitizer: DomSanitizer,
|
||||
@ -37,10 +41,30 @@ export class NodeContextMenuComponent implements OnInit {
|
||||
this.changeDetector.detectChanges();
|
||||
}
|
||||
|
||||
public open(node: Node, top: number, left: number) {
|
||||
public openMenuForNode(node: Node, top: number, left: number) {
|
||||
this.resetCapabilities();
|
||||
this.hasNodeCapabilities = true;
|
||||
|
||||
this.node = node;
|
||||
this.setPosition(top, left);
|
||||
|
||||
this.contextMenu.openMenu();
|
||||
}
|
||||
|
||||
public openMenuForDrawing(drawing: Drawing, top: number, left: number) {
|
||||
this.resetCapabilities();
|
||||
this.hasDrawingCapabilities = true;
|
||||
|
||||
this.drawing = drawing;
|
||||
this.setPosition(top, left);
|
||||
|
||||
this.contextMenu.openMenu();
|
||||
}
|
||||
|
||||
private resetCapabilities() {
|
||||
this.node = null;
|
||||
this.drawing = null;
|
||||
this.hasDrawingCapabilities = false;
|
||||
this.hasNodeCapabilities = false;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Server } from '../../../../../models/server';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||
import { NodeService } from '../../../../../services/node.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-move-layer-down-action',
|
||||
templateUrl: './move-layer-down-action.component.html'
|
||||
})
|
||||
export class MoveLayerDownActionComponent implements OnInit {
|
||||
@Input() server: Server;
|
||||
@Input() node: Node;
|
||||
|
||||
constructor(
|
||||
private nodesDataSource: NodesDataSource,
|
||||
private nodeService: NodeService
|
||||
) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
moveLayerDown() {
|
||||
this.node.z--;
|
||||
this.nodesDataSource.update(this.node);
|
||||
this.nodeService
|
||||
.update(this.server, this.node)
|
||||
.subscribe((node: Node) => {});
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Server } from '../../../../../models/server';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||
import { NodeService } from '../../../../../services/node.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-move-layer-up-action',
|
||||
templateUrl: './move-layer-up-action.component.html'
|
||||
})
|
||||
export class MoveLayerUpActionComponent implements OnInit {
|
||||
@Input() server: Server;
|
||||
@Input() node: Node;
|
||||
|
||||
constructor(
|
||||
private nodesDataSource: NodesDataSource,
|
||||
private nodeService: NodeService
|
||||
) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
moveLayerUp() {
|
||||
this.node.z++;
|
||||
this.nodesDataSource.update(this.node);
|
||||
this.nodeService
|
||||
.update(this.server, this.node)
|
||||
.subscribe((node: Node) => {});
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node">
|
||||
<span [matMenuTriggerFor]="contextMenu"></span>
|
||||
<mat-menu #contextMenu="matMenu" class="context-menu-items">
|
||||
<app-start-node-action [server]="server" [node]="node"></app-start-node-action>
|
||||
<app-stop-node-action [server]="server" [node]="node"></app-stop-node-action>
|
||||
<app-move-layer-up-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node"></app-move-layer-up-action>
|
||||
<app-move-layer-down-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node"></app-move-layer-down-action>
|
||||
</mat-menu>
|
||||
</div>
|
@ -121,7 +121,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<app-node-context-menu [project]="project" [server]="server"></app-node-context-menu>
|
||||
<app-context-menu [project]="project" [server]="server"></app-context-menu>
|
||||
</div>
|
||||
|
||||
<app-progress></app-progress>
|
||||
|
@ -12,7 +12,7 @@ import { ServerService } from "../../services/server.service";
|
||||
import { ProjectService } from '../../services/project.service';
|
||||
import { Server } from "../../models/server";
|
||||
import { Drawing } from "../../cartography/models/drawing";
|
||||
import { NodeContextMenuComponent } from "./node-context-menu/node-context-menu.component";
|
||||
import { ContextMenuComponent } from "./context-menu/context-menu.component";
|
||||
import { Template } from "../../models/template";
|
||||
import { NodeService } from "../../services/node.service";
|
||||
import { Symbol } from "../../models/symbol";
|
||||
@ -24,11 +24,14 @@ import { ProgressService } from "../../common/progress/progress.service";
|
||||
import { MapChangeDetectorRef } from '../../cartography/services/map-change-detector-ref';
|
||||
import { NodeContextMenu } from '../../cartography/events/nodes';
|
||||
import { NodeWidget } from '../../cartography/widgets/node';
|
||||
import { DrawingsWidget } from '../../cartography/widgets/drawings';
|
||||
import { DrawingService } from '../../services/drawing.service';
|
||||
import { MapNodeToNodeConverter } from '../../cartography/converters/map/map-node-to-node-converter';
|
||||
import { SettingsService, Settings } from '../../services/settings.service';
|
||||
import { D3MapComponent } from '../../cartography/components/d3-map/d3-map.component';
|
||||
import { ToolsService } from '../../services/tools.service';
|
||||
import { DrawingContextMenu } from '../../cartography/events/event-source';
|
||||
import { MapDrawingToDrawingConverter } from '../../cartography/converters/map/map-drawing-to-drawing-converter';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -66,7 +69,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
|
||||
private inReadOnlyMode = false;
|
||||
|
||||
@ViewChild(NodeContextMenuComponent) nodeContextMenu: NodeContextMenuComponent;
|
||||
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
|
||||
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
@ -81,7 +84,9 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
private projectWebServiceHandler: ProjectWebServiceHandler,
|
||||
private mapChangeDetectorRef: MapChangeDetectorRef,
|
||||
private nodeWidget: NodeWidget,
|
||||
private drawingsWidget: DrawingsWidget,
|
||||
private mapNodeToNode: MapNodeToNodeConverter,
|
||||
private mapDrawingToDrawing: MapDrawingToDrawingConverter,
|
||||
private nodesDataSource: NodesDataSource,
|
||||
private linksDataSource: LinksDataSource,
|
||||
private drawingsDataSource: DrawingsDataSource,
|
||||
@ -189,16 +194,26 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
setUpMapCallbacks() {
|
||||
const onContextMenu = this.nodeWidget.onContextMenu.subscribe((eventNode: NodeContextMenu) => {
|
||||
const onNodeContextMenu = this.nodeWidget.onContextMenu.subscribe((eventNode: NodeContextMenu) => {
|
||||
const node = this.mapNodeToNode.convert(eventNode.node);
|
||||
this.nodeContextMenu.open(
|
||||
this.contextMenu.openMenuForNode(
|
||||
node,
|
||||
eventNode.event.clientY,
|
||||
eventNode.event.clientX
|
||||
);
|
||||
});
|
||||
|
||||
this.subscriptions.push(onContextMenu);
|
||||
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.subscriptions.push(onNodeContextMenu);
|
||||
this.subscriptions.push(onDrawingContextMenu);
|
||||
this.mapChangeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user