Initial implementation

This commit is contained in:
Piotr Pekala 2019-05-31 07:24:28 -07:00
parent 889c48be65
commit 7342436948
9 changed files with 94 additions and 32 deletions

View File

@ -1,6 +1,8 @@
import { TextElement } from '../models/drawings/text-element'; import { TextElement } from '../models/drawings/text-element';
import { MapDrawing } from '../models/map/map-drawing'; import { MapDrawing } from '../models/map/map-drawing';
import { MapLink } from '../models/map/map-link'; import { MapLink } from '../models/map/map-link';
import { MapLinkNode } from '../models/map/map-link-node';
import { MapLabel } from '../models/map/map-label';
export class DataEventSource<T> { export class DataEventSource<T> {
constructor(public datum: T, public dx: number, public dy: number) {} constructor(public datum: T, public dx: number, public dy: number) {}
@ -33,5 +35,13 @@ export class DrawingContextMenu {
} }
export class LinkContextMenu { export class LinkContextMenu {
constructor(public event:any, public link: MapLink) {} constructor(public event: any, public link: MapLink) {}
}
export class InterfaceLabelContextMenu {
constructor(public event: any, public interfaceLabel: MapLinkNode) {}
}
export class LabelContextMenu {
constructor(public event: any, public label: MapLabel) {}
} }

View File

@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'; import { Injectable, EventEmitter } from '@angular/core';
import { SVGSelection } from '../models/types'; import { SVGSelection } from '../models/types';
import { CssFixer } from '../helpers/css-fixer'; import { CssFixer } from '../helpers/css-fixer';
@ -10,9 +10,11 @@ import { MapLinkNode } from '../models/map/map-link-node';
import { MapNode } from '../models/map/map-node'; import { MapNode } from '../models/map/map-node';
import { Draggable } from '../events/draggable'; import { Draggable } from '../events/draggable';
import { MapSettingsManager } from '../managers/map-settings-manager'; import { MapSettingsManager } from '../managers/map-settings-manager';
import { InterfaceLabelContextMenu } from '../events/event-source';
@Injectable() @Injectable()
export class InterfaceLabelWidget { export class InterfaceLabelWidget {
public onContextMenu = new EventEmitter<InterfaceLabelContextMenu>();
public draggable = new Draggable<SVGGElement, MapLinkNode>(); public draggable = new Draggable<SVGGElement, MapLinkNode>();
static SURROUNDING_TEXT_BORDER = 5; static SURROUNDING_TEXT_BORDER = 5;
@ -30,6 +32,8 @@ export class InterfaceLabelWidget {
} }
draw(selection: SVGSelection) { draw(selection: SVGSelection) {
const self = this;
const link_node_position = selection const link_node_position = selection
.selectAll<SVGGElement, MapLinkNode>('g.link_node_position') .selectAll<SVGGElement, MapLinkNode>('g.link_node_position')
.data((link: MapLink) => [[link.source, link.nodes[0]], [link.target, link.nodes[1]]]); .data((link: MapLink) => [[link.source, link.nodes[0]], [link.target, link.nodes[1]]]);
@ -68,7 +72,12 @@ export class InterfaceLabelWidget {
.attr('class', 'interface_label noselect') .attr('class', 'interface_label noselect')
.attr('interface_label_id', (i: MapLinkNode) => `${i.id}`); .attr('interface_label_id', (i: MapLinkNode) => `${i.id}`);
const merge = labels.merge(enter); const merge = labels
.merge(enter)
.on('contextmenu', (n: MapLinkNode, i: number) => {
event.preventDefault();
self.onContextMenu.emit(new InterfaceLabelContextMenu(event, n));
});
// update label // update label
merge merge

View File

@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'; import { Injectable, EventEmitter } from '@angular/core';
import { Widget } from './widget'; import { Widget } from './widget';
import { SVGSelection } from '../models/types'; import { SVGSelection } from '../models/types';
@ -10,9 +10,11 @@ import { SelectionManager } from '../managers/selection-manager';
import { Draggable } from '../events/draggable'; import { Draggable } from '../events/draggable';
import { MapLabel } from '../models/map/map-label'; import { MapLabel } from '../models/map/map-label';
import { MapSettingsManager } from '../managers/map-settings-manager'; import { MapSettingsManager } from '../managers/map-settings-manager';
import { LabelContextMenu } from '../events/event-source';
@Injectable() @Injectable()
export class LabelWidget implements Widget { export class LabelWidget implements Widget {
public onContextMenu = new EventEmitter<LabelContextMenu>();
public draggable = new Draggable<SVGGElement, MapLabel>(); public draggable = new Draggable<SVGGElement, MapLabel>();
static NODE_LABEL_MARGIN = 3; static NODE_LABEL_MARGIN = 3;
@ -29,6 +31,7 @@ export class LabelWidget implements Widget {
} }
public draw(view: SVGSelection) { public draw(view: SVGSelection) {
const self = this;
const label_view = view.selectAll<SVGGElement, MapLabel>('g.label_container').data((node: MapNode) => { const label_view = view.selectAll<SVGGElement, MapLabel>('g.label_container').data((node: MapNode) => {
return [node.label]; return [node.label];
}); });
@ -39,7 +42,12 @@ export class LabelWidget implements Widget {
.attr('class', 'label_container') .attr('class', 'label_container')
.attr('label_id', (label: MapLabel) => label.id); .attr('label_id', (label: MapLabel) => label.id);
const merge = label_view.merge(label_enter); const merge = label_view
.merge(label_enter)
.on('contextmenu', (n: MapLabel, i: number) => {
event.preventDefault();
self.onContextMenu.emit(new LabelContextMenu(event, n));
});
this.drawLabel(merge); this.drawLabel(merge);
@ -63,7 +71,8 @@ export class LabelWidget implements Widget {
label_body_enter.append<SVGRectElement>('rect').attr('class', 'label_selection'); label_body_enter.append<SVGRectElement>('rect').attr('class', 'label_selection');
const label_body_merge = label_body.merge(label_body_enter); const label_body_merge = label_body
.merge(label_body_enter);
label_body_merge label_body_merge
.select<SVGTextElement>('text.label') .select<SVGTextElement>('text.label')

View File

@ -38,10 +38,6 @@ export class NodeWidget implements Widget {
const node_body_merge = node_body const node_body_merge = node_body
.merge(node_body_enter) .merge(node_body_enter)
.classed('selected', (n: MapNode) => this.selectionManager.isSelected(n)) .classed('selected', (n: MapNode) => this.selectionManager.isSelected(n))
.on('contextmenu', function(n: MapNode, i: number) {
event.preventDefault();
self.onContextMenu.emit(new NodeContextMenu(event, n));
})
.on('click', (node: MapNode) => { .on('click', (node: MapNode) => {
this.nodesEventSource.clicked.emit(new ClickedDataEvent<MapNode>(node, event.clientX, event.clientY)); this.nodesEventSource.clicked.emit(new ClickedDataEvent<MapNode>(node, event.clientX, event.clientY));
}); });
@ -49,6 +45,10 @@ export class NodeWidget implements Widget {
// update image of node // update image of node
node_body_merge node_body_merge
.select<SVGImageElement>('image') .select<SVGImageElement>('image')
.on('contextmenu', function(n: MapNode, i: number) {
event.preventDefault();
self.onContextMenu.emit(new NodeContextMenu(event, n));
})
.attr('xnode:href', (n: MapNode) => n.symbolUrl) .attr('xnode:href', (n: MapNode) => n.symbolUrl)
.attr('width', (n: MapNode) => n.width) .attr('width', (n: MapNode) => n.width)
.attr('height', (n: MapNode) => n.height) .attr('height', (n: MapNode) => n.height)

View File

@ -4,6 +4,7 @@ import { Project } from '../../../../../models/project';
import { Drawing } from '../../../../../cartography/models/drawing'; import { Drawing } from '../../../../../cartography/models/drawing';
import { MatDialog } from '@angular/material'; import { MatDialog } from '@angular/material';
import { TextEditorDialogComponent } from '../../../drawings-editors/text-editor/text-editor.component'; import { TextEditorDialogComponent } from '../../../drawings-editors/text-editor/text-editor.component';
import { Label } from '../../../../../cartography/models/label';
@Component({ @Component({
selector: 'app-edit-text-action', selector: 'app-edit-text-action',
@ -13,6 +14,7 @@ export class EditTextActionComponent implements OnInit {
@Input() server: Server; @Input() server: Server;
@Input() project: Project; @Input() project: Project;
@Input() drawing: Drawing; @Input() drawing: Drawing;
@Input() label: Label;
constructor(private dialog: MatDialog) {} constructor(private dialog: MatDialog) {}
@ -27,5 +29,6 @@ export class EditTextActionComponent implements OnInit {
instance.server = this.server; instance.server = this.server;
instance.project = this.project; instance.project = this.project;
instance.drawing = this.drawing; instance.drawing = this.drawing;
instance.label = this.label;
} }
} }

View File

@ -14,10 +14,11 @@
[drawing]="drawings[0]" [drawing]="drawings[0]"
></app-edit-style-action> ></app-edit-style-action>
<app-edit-text-action <app-edit-text-action
*ngIf="drawings.length===1 && hasTextCapabilities" *ngIf="drawings.length===1 && hasTextCapabilities || labels.length===1"
[server]="server" [server]="server"
[project]="project" [project]="project"
[drawing]="drawings[0]" [drawing]="drawings[0]"
[label]="labels[0]"
></app-edit-text-action> ></app-edit-text-action>
<app-move-layer-up-action <app-move-layer-up-action
*ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)" *ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)"
@ -60,7 +61,7 @@
[link]="links[0]" [link]="links[0]"
></app-suspend-link-action> ></app-suspend-link-action>
<app-delete-action <app-delete-action
*ngIf="!projectService.isReadOnly(project)" *ngIf="!projectService.isReadOnly(project) && (drawings.length>0 || nodes.length>0 || links.length>0)"
[server]="server" [server]="server"
[nodes]="nodes" [nodes]="nodes"
[drawings]="drawings" [drawings]="drawings"

View File

@ -1,15 +1,15 @@
<h1 mat-dialog-title>Text editor</h1> <h1 mat-dialog-title>Text editor</h1>
<div class="modal-form-container"> <div class="modal-form-container">
<mat-form-field> <!-- <mat-form-field>
<input matInput placeholder="Fill color" type="color" (ngModelChange)="changeTextColor($event)" [(ngModel)]="element.fill"> <input matInput placeholder="Fill color" type="color" (ngModelChange)="changeTextColor($event)" [(ngModel)]="element.fill">
</mat-form-field> </mat-form-field> -->
<mat-form-field> <mat-form-field>
<input matInput placeholder="Rotation" type="text" [(ngModel)]="rotation"> <input matInput placeholder="Rotation" type="text" [(ngModel)]="rotation">
</mat-form-field> </mat-form-field>
<textarea #textArea id="textArea" class="text" [(ngModel)]="element.text"> </textarea> <!-- <textarea #textArea id="textArea" class="text" [(ngModel)]="element.text"> </textarea> -->
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>

View File

@ -8,6 +8,7 @@ import { MapDrawingToSvgConverter } from '../../../../cartography/converters/map
import { DrawingService } from '../../../../services/drawing.service'; import { DrawingService } from '../../../../services/drawing.service';
import { DrawingsDataSource } from '../../../../cartography/datasources/drawings-datasource'; import { DrawingsDataSource } from '../../../../cartography/datasources/drawings-datasource';
import { TextElement } from '../../../../cartography/models/drawings/text-element'; import { TextElement } from '../../../../cartography/models/drawings/text-element';
import { Label } from '../../../../cartography/models/label';
@Component({ @Component({
selector: 'app-text-editor', selector: 'app-text-editor',
@ -20,6 +21,7 @@ export class TextEditorDialogComponent implements OnInit {
server: Server; server: Server;
project: Project; project: Project;
drawing: Drawing; drawing: Drawing;
label: Label;
element: TextElement; element: TextElement;
rotation: string; rotation: string;
@ -33,13 +35,20 @@ export class TextEditorDialogComponent implements OnInit {
) {} ) {}
ngOnInit() { ngOnInit() {
this.rotation = this.drawing.rotation.toString(); console.log(this.label);
if (this.drawing) {
this.element = this.drawing.element as TextElement; this.rotation = this.drawing.rotation.toString();
this.renderer.setStyle(this.textArea.nativeElement, 'color', this.element.fill); this.element = this.drawing.element as TextElement;
this.renderer.setStyle(this.textArea.nativeElement, 'font-family', this.element.font_family); this.renderer.setStyle(this.textArea.nativeElement, 'color', this.element.fill);
this.renderer.setStyle(this.textArea.nativeElement, 'font-size', `${this.element.font_size}pt`); this.renderer.setStyle(this.textArea.nativeElement, 'font-family', this.element.font_family);
this.renderer.setStyle(this.textArea.nativeElement, 'font-weight', this.element.font_weight); this.renderer.setStyle(this.textArea.nativeElement, 'font-size', `${this.element.font_size}pt`);
this.renderer.setStyle(this.textArea.nativeElement, 'font-weight', this.element.font_weight);
} else if (this.label) {
this.rotation = this.label.rotation.toString();
this.element = new TextElement();
this.element.text = this.label.text;
this.element.fill = "#ffffff";
}
} }
onNoClick() { onNoClick() {
@ -47,18 +56,22 @@ export class TextEditorDialogComponent implements OnInit {
} }
onYesClick() { onYesClick() {
this.drawing.rotation = +this.rotation; if (this.drawing) {
this.drawing.element = this.element; this.drawing.rotation = +this.rotation;
this.drawing.element = this.element;
let mapDrawing = this.drawingToMapDrawingConverter.convert(this.drawing); let mapDrawing = this.drawingToMapDrawingConverter.convert(this.drawing);
mapDrawing.element = this.drawing.element; mapDrawing.element = this.drawing.element;
this.drawing.svg = this.mapDrawingToSvgConverter.convert(mapDrawing); this.drawing.svg = this.mapDrawingToSvgConverter.convert(mapDrawing);
this.drawingService.update(this.server, this.drawing).subscribe((serverDrawing: Drawing) => { this.drawingService.update(this.server, this.drawing).subscribe((serverDrawing: Drawing) => {
this.drawingsDataSource.update(serverDrawing); this.drawingsDataSource.update(serverDrawing);
this.dialogRef.close(); this.dialogRef.close();
}); });
} else if(this.label) {
}
} }
changeTextColor(changedColor) { changeTextColor(changedColor) {

View File

@ -30,7 +30,7 @@ import { MapNodeToNodeConverter } from '../../cartography/converters/map/map-nod
import { SettingsService, Settings } from '../../services/settings.service'; import { SettingsService, Settings } from '../../services/settings.service';
import { D3MapComponent } from '../../cartography/components/d3-map/d3-map.component'; import { D3MapComponent } from '../../cartography/components/d3-map/d3-map.component';
import { ToolsService } from '../../services/tools.service'; import { ToolsService } from '../../services/tools.service';
import { DrawingContextMenu, LinkContextMenu } from '../../cartography/events/event-source'; import { DrawingContextMenu, LinkContextMenu, LabelContextMenu, InterfaceLabelContextMenu } from '../../cartography/events/event-source';
import { MapDrawingToDrawingConverter } from '../../cartography/converters/map/map-drawing-to-drawing-converter'; import { MapDrawingToDrawingConverter } from '../../cartography/converters/map/map-drawing-to-drawing-converter';
import { SelectionManager } from '../../cartography/managers/selection-manager'; import { SelectionManager } from '../../cartography/managers/selection-manager';
import { SelectionTool } from '../../cartography/tools/selection-tool'; import { SelectionTool } from '../../cartography/tools/selection-tool';
@ -44,6 +44,8 @@ import { MapLink } from '../../cartography/models/map/map-link';
import { MapLinkToLinkConverter } from '../../cartography/converters/map/map-link-to-link-converter'; import { MapLinkToLinkConverter } from '../../cartography/converters/map/map-link-to-link-converter';
import { LinkWidget } from '../../cartography/widgets/link'; import { LinkWidget } from '../../cartography/widgets/link';
import { NodeCreatedLabelStylesFixer } from './helpers/node-created-label-styles-fixer'; import { NodeCreatedLabelStylesFixer } from './helpers/node-created-label-styles-fixer';
import { InterfaceLabelWidget } from '../../cartography/widgets/interface-label';
import { LabelWidget } from '../../cartography/widgets/label';
@Component({ @Component({
@ -98,6 +100,8 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
private nodeWidget: NodeWidget, private nodeWidget: NodeWidget,
private drawingsWidget: DrawingsWidget, private drawingsWidget: DrawingsWidget,
private linkWidget: LinkWidget, private linkWidget: LinkWidget,
private labelWidget: LabelWidget,
private interfaceLabelWidget: InterfaceLabelWidget,
private mapNodeToNode: MapNodeToNodeConverter, private mapNodeToNode: MapNodeToNodeConverter,
private mapDrawingToDrawing: MapDrawingToDrawingConverter, private mapDrawingToDrawing: MapDrawingToDrawingConverter,
private mapLabelToLabel: MapLabelToLabelConverter, private mapLabelToLabel: MapLabelToLabelConverter,
@ -238,6 +242,17 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.pageY, eventDrawing.event.pageX); this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.pageY, eventDrawing.event.pageX);
}); });
const onLabelContextMenu = this.labelWidget.onContextMenu.subscribe((eventLabel: LabelContextMenu) => {
const label = this.mapLabelToLabel.convert(eventLabel.label);
this.contextMenu.openMenuForLabel(label, eventLabel.event.pageY, eventLabel.event.pageX);
});
const onInterfaceLabelContextMenu = this.interfaceLabelWidget.onContextMenu.subscribe((eventInterfaceLabel: InterfaceLabelContextMenu) => {
console.log("!!!!!!!!!! interface label");
console.log(eventInterfaceLabel);
//const interfaceLabel = this.mapLinkToLink.convert(eventInterfaceLabel.interfaceLabel);
});
const onContextMenu = this.selectionTool.contextMenuOpened.subscribe((event) => { const onContextMenu = this.selectionTool.contextMenuOpened.subscribe((event) => {
const selectedItems = this.selectionManager.getSelected(); const selectedItems = this.selectionManager.getSelected();
if (selectedItems.length === 0 || !(event instanceof MouseEvent)) return; if (selectedItems.length === 0 || !(event instanceof MouseEvent)) return;
@ -266,6 +281,8 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.subscriptions.push(onNodeContextMenu); this.subscriptions.push(onNodeContextMenu);
this.subscriptions.push(onDrawingContextMenu); this.subscriptions.push(onDrawingContextMenu);
this.subscriptions.push(onContextMenu); this.subscriptions.push(onContextMenu);
this.subscriptions.push(onLabelContextMenu);
this.subscriptions.push(onInterfaceLabelContextMenu);
this.mapChangeDetectorRef.detectChanges(); this.mapChangeDetectorRef.detectChanges();
} }