Code responsible for adding text refactored

This commit is contained in:
Piotr Pekala 2019-01-04 03:17:10 -08:00
parent c9b0eca05b
commit 37ec1cc21d
15 changed files with 84 additions and 193 deletions

View File

@ -42,7 +42,6 @@ import { SelectionSelectComponent } from './components/selection-select/selectio
import { DraggableSelectionComponent } from './components/draggable-selection/draggable-selection.component';
import { MapSettingsManager } from './managers/map-settings-manager';
import { DrawingResizingComponent } from './components/drawing-resizing/drawing-resizing.component';
import { TextAddingComponent } from './components/text-adding/text-adding.component';
import { TextEditingComponent } from './components/text-editing/text-editing.component';
import { FontBBoxCalculator } from './helpers/font-bbox-calculator';
import { StylesToFontConverter } from './converters/styles-to-font-converter';
@ -63,7 +62,6 @@ import { TemporaryTextElementComponent } from './components/temporary-text-eleme
D3MapComponent,
ExperimentalMapComponent,
DrawingResizingComponent,
TextAddingComponent,
TextEditingComponent,
TemporaryTextElementComponent,
...ANGULAR_MAP_DECLARATIONS,

View File

@ -12,6 +12,5 @@
<app-selection-control></app-selection-control>
<app-selection-select></app-selection-select>
<app-temporary-text-element [svg]="svg"></app-temporary-text-element>
<app-text-adding></app-text-adding>
<app-text-editing></app-text-editing>
<app-draggable-selection [svg]="svg"></app-draggable-selection>

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 480 B

View File

@ -19,9 +19,7 @@ import { Symbol } from '../../../models/symbol';
import { GraphDataManager } from '../../managers/graph-data-manager';
import { MapSettingsManager } from '../../managers/map-settings-manager';
import { TextEditingTool } from '../../tools/text-editing-tool';
import { TextAddingComponent } from '../text-adding/text-adding.component';
import { Server } from '../../../models/server';
import { TextAddingTool } from '../../tools/text-adding-tool';
import { ToolsService } from '../../../services/tools.service';
@ -41,7 +39,6 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
@Input() height = 600;
@ViewChild('svg') svgRef: ElementRef;
@ViewChild(TextAddingComponent) textAddingComponent: TextAddingComponent;
private parentNativeElement: any;
private svg: Selection<SVGSVGElement, any, null, undefined>;
@ -65,7 +62,6 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
protected interfaceLabelWidget: InterfaceLabelWidget,
protected selectionToolWidget: SelectionTool,
protected movingToolWidget: MovingTool,
protected textAddingToolWidget: TextAddingTool,
protected textEditingToolWidget: TextEditingTool,
public graphLayout: GraphLayout,
private toolsService: ToolsService
@ -114,13 +110,6 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
}
});
this.subscriptions.push(
this.toolsService.isTextAddingToolActivated.subscribe((value: boolean) => {
//this.textAddingToolWidget.setEnabled(value);
this.mapChangeDetectorRef.detectChanges();
})
);
this.subscriptions.push(
this.toolsService.isTextEditingToolActivated.subscribe((value: boolean) => {
this.textEditingToolWidget.setEnabled(value);

View File

@ -13,10 +13,9 @@ export class TemporaryTextElementComponent implements OnInit, OnDestroy {
@ViewChild('temporaryTextElement') temporaryTextElement: ElementRef;
@Input('svg') svg: SVGSVGElement;
//should cover all style variables that can change
private leftPosition: string;
private topPosition: string;
private innerText: string;
private leftPosition: string = '0px';
private topPosition: string = '0px';
private innerText: string = '';
private isActive: boolean = true;
private mapListener: Function;
private textListener: Function;
@ -25,14 +24,11 @@ export class TemporaryTextElementComponent implements OnInit, OnDestroy {
constructor(
private drawingsEventSource: DrawingsEventSource,
private toolsService: ToolsService
){
this.leftPosition = '100px';
this.topPosition = '100px';
this.innerText = '';
}
){}
ngOnInit(){
this.toolsService.isTextAddingToolActivated.subscribe((isActive: boolean) => {
this.isActive = isActive;
isActive ? this.activate() : this.decativate()
});
}
@ -45,11 +41,10 @@ export class TemporaryTextElementComponent implements OnInit, OnDestroy {
this.temporaryTextElement.nativeElement.focus();
let textListener = () => {
console.log("textListener: ", this.innerText);
this.drawingsEventSource.textAdded.emit(new TextAddedDataEvent(this.innerText.replace(/\n$/, ""), event.clientX, event.clientY));
this.drawingsEventSource.textAdded.emit(new TextAddedDataEvent(this.temporaryTextElement.nativeElement.innerText.replace(/\n$/, ""), event.clientX, event.clientY));
this.svg.removeEventListener('click', this.mapListener as EventListenerOrEventListenerObject);
this.temporaryTextElement.nativeElement.removeEventListener('focusout', this.textListener);
this.innerText = '';
this.isActive = false;
}
this.textListener = textListener;
this.temporaryTextElement.nativeElement.addEventListener('focusout', this.textListener);
@ -64,6 +59,6 @@ export class TemporaryTextElementComponent implements OnInit, OnDestroy {
}
ngOnDestroy(){
this.toolsService.isTextAddingToolActivated.unsubscribe();
}
}

View File

@ -1,31 +0,0 @@
import { Component, OnInit, OnDestroy } from "@angular/core";
import { select } from 'd3-selection';
import { Context } from "../../models/context";
import { TextAddingTool } from '../../tools/text-adding-tool';
import { Subscription } from 'rxjs';
import { DrawingsEventSource } from '../../events/drawings-event-source';
import { TextAddedDataEvent } from '../../events/event-source';
@Component({
selector: 'app-text-adding',
template: `<ng-content></ng-content>`,
styleUrls: ['./text-adding.component.scss']
})
export class TextAddingComponent implements OnInit, OnDestroy {
textAddingFinished: Subscription;
constructor(
private textAddingTool: TextAddingTool,
private drawingEventSource: DrawingsEventSource
){}
ngOnInit() {
this.textAddingFinished = this.textAddingTool.addingFinished.subscribe((evt: TextAddedDataEvent) => {
this.drawingEventSource.textAdded.emit(evt);
})
}
ngOnDestroy() {
this.textAddingFinished.unsubscribe();
}
}

View File

@ -5,7 +5,6 @@ import { DrawingsWidget } from './widgets/drawings';
import { DrawingLineWidget } from './widgets/drawing-line';
import { SelectionTool } from './tools/selection-tool';
import { MovingTool } from './tools/moving-tool';
import {TextAddingTool} from './tools/text-adding-tool';
import {TextEditingTool} from './tools/text-editing-tool';
import { LayersWidget } from './widgets/layers';
import { LinkWidget } from './widgets/link';
@ -30,7 +29,6 @@ export const D3_MAP_IMPORTS = [
DrawingLineWidget,
SelectionTool,
MovingTool,
TextAddingTool,
TextEditingTool,
LayersWidget,
LinkWidget,

View File

@ -1,74 +0,0 @@
import { Injectable, EventEmitter } from "@angular/core";
import { TextAddedDataEvent } from '../events/event-source';
import { DrawingsEventSource } from '../events/drawings-event-source';
@Injectable()
export class TextAddingTool {
private listener: Function;
private temporaryElement: HTMLDivElement;
public addingFinished = new EventEmitter<any>();
constructor(
private drawingEventSource: DrawingsEventSource,
){}
public setEnabled(enabled){
// if (enabled){
// this.activate();
// } else {
// this.deactivate();
// }
}
private deactivate(){
var map = document.getElementsByClassName('map')[0];
map.removeEventListener('click', this.listener as EventListenerOrEventListenerObject);
}
private activate(){
var map = document.getElementsByClassName('map')[0];
let addTextListener = (event: MouseEvent) => {
this.temporaryElement = this.getTemporaryElement(event.clientX, event.clientY);
document.body.appendChild(this.temporaryElement);
this.temporaryElement.focus();
document.body.style.cursor = "text";
this.temporaryElement.addEventListener("focusout", () => {
let innerText = this.temporaryElement.innerText;
this.addingFinished.emit(new TextAddedDataEvent(innerText.replace(/\n$/, ""), event.clientX, event.clientY));
this.drawingEventSource.textSaved.subscribe((evt:boolean) => {
if(evt){
this.temporaryElement.remove();
document.body.style.cursor = "default";
}
});
});
}
map.removeEventListener('click', this.listener as EventListenerOrEventListenerObject);
this.listener = addTextListener;
map.addEventListener('click', this.listener as EventListenerOrEventListenerObject, {once : true});
}
private getTemporaryElement(x:number, y:number): HTMLDivElement{
var elem = document.createElement('div');
elem.className = "temporaryElement";
elem.style.paddingLeft = "4px";
elem.style.width = "fit-content";
elem.style.left = x.toString() + 'px';
elem.style.top = y.toString() + 'px';
elem.style.position = "absolute";
elem.style.zIndex = "99";
elem.style.fontFamily = "Noto Sans";
elem.style.fontSize = "11pt";
elem.style.fontWeight = "bold";
elem.style.color = "#000000";
elem.setAttribute("contenteditable", "true");
elem.innerText = "";
return elem;
}
}

View File

@ -0,0 +1,63 @@
import { TextAddedComponent } from "./text-added.component";
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
import { DrawingService } from '../../../services/drawing.service';
import { DrawingsDataSource } from '../../../cartography/datasources/drawings-datasource';
import { DrawingsEventSource } from '../../../cartography/events/drawings-event-source';
import { MapDrawingToSvgConverter } from '../../../cartography/converters/map/map-drawing-to-svg-converter';
import { MockedDrawingService, MockedDrawingsDataSource } from '../../project-map/project-map.component.spec';
import { DefaultDrawingsFactory } from '../../../cartography/helpers/default-drawings-factory';
import { Context } from '../../../cartography/models/context';
import { TextAddedDataEvent } from '../../../cartography/events/event-source';
import { Observable } from 'rxjs';
import { TextElementFactory } from '../../../cartography/helpers/drawings-factory/text-element-factory';
import { EllipseElementFactory } from '../../../cartography/helpers/drawings-factory/ellipse-element-factory';
import { RectangleElementFactory } from '../../../cartography/helpers/drawings-factory/rectangle-element-factory';
import { LineElementFactory } from '../../../cartography/helpers/drawings-factory/line-element-factory';
import { Project } from '../../../models/project';
describe('TextAddedComponent', () => {
let component: TextAddedComponent;
let fixture: ComponentFixture<TextAddedComponent>;
let mockedDrawingService = new MockedDrawingService;
let mockedDrawingsDataSource = new MockedDrawingsDataSource;
let mockedDrawingsEventSource = new DrawingsEventSource;
let mockedDrawingsFactory = new DefaultDrawingsFactory(new TextElementFactory,
new EllipseElementFactory, new RectangleElementFactory, new LineElementFactory);
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{ provide: DrawingService, useValue: mockedDrawingService },
{ provide: DrawingsDataSource, useValue: mockedDrawingsDataSource },
{ provide: DrawingsEventSource, useValue: mockedDrawingsEventSource },
{ provide: DefaultDrawingsFactory, useValue: mockedDrawingsFactory },
{ provide: MapDrawingToSvgConverter, useClass: MapDrawingToSvgConverter },
{ provide: Context, useClass: Context}
],
declarations: [
TextAddedComponent
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TextAddedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call drawing service when text added', () => {
component.project = { project_id: "sampleId" } as Project;
const textAddedDataEvent = new TextAddedDataEvent("savedText", 0 ,0);
spyOn(mockedDrawingService, 'add').and.returnValue( Observable.of({}));
mockedDrawingsEventSource.textAdded.emit(textAddedDataEvent);
expect(mockedDrawingService.add).toHaveBeenCalled();
});
});

View File

@ -10,6 +10,7 @@ import { TextElement } from '../../../cartography/models/drawings/text-element';
import { Server } from '../../../models/server';
import { Project } from '../../../models/project';
import { Drawing } from '../../../cartography/models/drawing';
import { Context } from '../../../cartography/models/context';
@Component({
@ -28,7 +29,8 @@ export class TextAddedComponent implements OnInit, OnDestroy{
private drawingsDataSource: DrawingsDataSource,
private drawingsEventSource: DrawingsEventSource,
private drawingsFactory: DefaultDrawingsFactory,
private mapDrawingToSvgConverter: MapDrawingToSvgConverter
private mapDrawingToSvgConverter: MapDrawingToSvgConverter,
private context: Context
){}
ngOnInit(){
@ -36,14 +38,12 @@ export class TextAddedComponent implements OnInit, OnDestroy{
}
onTextAdded(evt: TextAddedDataEvent){
console.log(evt);
let drawing = this.drawingsFactory.getDrawingMock("text");
(drawing.element as TextElement).text = "evtsavedText";
(drawing.element as TextElement).text = evt.savedText;
let svgText = this.mapDrawingToSvgConverter.convert(drawing);
this.drawingService
.add(this.server, this.project.project_id, -55, -400, svgText)
.add(this.server, this.project.project_id, evt.x - this.context.getZeroZeroTransformationPoint().x, evt.y - this.context.getZeroZeroTransformationPoint().y, svgText)
.subscribe((serverDrawing: Drawing) => {
this.drawingsDataSource.add(serverDrawing);
this.drawingSaved.emit(true);

View File

@ -8,7 +8,6 @@ import { Server } from '../../../models/server';
import { MapDrawing } from '../../../cartography/models/map/map-drawing';
import { Drawing } from '../../../cartography/models/drawing';
import { Context } from '../../../cartography/models/context';
import { TextElement } from '../../../cartography/models/drawings/text-element';
@Component({
@ -36,11 +35,9 @@ export class AddDrawingComponent implements OnChanges {
if(changes['selectedDrawing'] && !changes['selectedDrawing'].isFirstChange()){
if(this.availableDrawings.includes(changes['selectedDrawing'].currentValue)){
this.addDrawing(changes['selectedDrawing'].currentValue);
} else if (changes['selectedDrawing'].currentValue === "text") {
//this.addText();
} else {
} else if (!(changes['selectedDrawing'].currentValue === "text")) {
document.getElementsByClassName('map')[0].removeEventListener('click', this.drawListener as EventListenerOrEventListenerObject);
}
}
}
}
@ -65,50 +62,4 @@ export class AddDrawingComponent implements OnChanges {
this.drawListener = listener;
map.addEventListener('click', this.drawListener as EventListenerOrEventListenerObject, {once : true});
}
addText(){
let addTextListener = (event: MouseEvent) => {
let textBox = document.createElement('div');
textBox.style.width = "fit-content";
textBox.style.left = event.clientX.toString() + 'px';
textBox.style.top = (event.clientY - 10).toString() + 'px';
textBox.style.position = "absolute";
textBox.style.zIndex = "99";
textBox.style.fontFamily = "Noto Sans";
textBox.style.fontSize = "11pt";
textBox.style.fontWeight = "bold";
textBox.style.color = "#000000";
textBox.setAttribute("contenteditable", "true");
document.body.appendChild(textBox);
textBox.innerText = "";
textBox.focus();
document.body.style.cursor = "text";
textBox.addEventListener("focusout", () => {
let savedText = textBox.innerText;
let drawing = this.drawingsFactory.getDrawingMock("text");
(drawing.element as TextElement).text = savedText;
let svgText = this.mapDrawingToSvgConverter.convert(drawing);
this.drawingService
.add(this.server, this.project.project_id, event.clientX - this.context.getZeroZeroTransformationPoint().x, event.clientY - this.context.getZeroZeroTransformationPoint().y, svgText)
.subscribe((serverDrawing: Drawing) => {
document.body.style.cursor = "default";
textBox.remove();
this.drawingsDataSource.add(serverDrawing);
this.drawingSaved.emit(true);
});
});
}
let map = document.getElementsByClassName('map')[0];
map.removeEventListener('click', this.drawListener as EventListenerOrEventListenerObject);
this.drawListener = addTextListener;
map.addEventListener('click', this.drawListener as EventListenerOrEventListenerObject, {once : true});
}
}

View File

@ -144,17 +144,20 @@
<app-draw-link-tool *ngIf="tools.draw_link"></app-draw-link-tool>
<app-add-drawing
[project]="project"
[server]="server"
[project]="project"
[selectedDrawing]="selectedDrawing"
(drawingSaved)="onDrawingSaved($event)">
</app-add-drawing>
<app-drawing-dragged [server]="server"></app-drawing-dragged>
<app-drawing-resized [server]="server"></app-drawing-resized>
<app-interface-label-dragged [server]="server"></app-interface-label-dragged>
<app-link-created [server]="server" [project]="project"></app-link-created>
<app-node-dragged [server]="server"></app-node-dragged>
<app-node-label-dragged [server]="server"></app-node-label-dragged>
<app-text-added [server]="server" [project]="project"></app-text-added>
<app-text-added
[server]="server"
[project]="project"
(drawingSaved)="onDrawingSaved($event)"
></app-text-added>
<app-text-edited [server]="server"></app-text-edited>