import { AfterContentInit, ContentChildren, Directive, EventEmitter, Input, OnChanges, OnDestroy, Output, QueryList, SimpleChanges } from '@angular/core';
import { Subscription } from 'rxjs';
import { PolylineManager } from '../services/managers/polyline-manager';
import { MVCEvent } from '../utils/mvcarray-utils';
import { AgmPolylineIcon } from './polyline-icon';
import { AgmPolylinePoint } from './polyline-point';
let polylineId = 0;
@Directive({
selector: 'agm-polyline',
})
export class AgmPolyline implements OnDestroy, OnChanges, AfterContentInit {
@Input() clickable = true;
@Input('polylineDraggable') draggable = false;
@Input() editable = false;
@Input() geodesic = false;
@Input() strokeColor: string;
@Input() strokeOpacity: number;
@Input() strokeWeight: number;
@Input() visible = true;
@Input() zIndex: number;
@Output() lineClick: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineDblClick: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineDrag: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() lineDragEnd: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() lineDragStart: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() lineMouseDown: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineMouseMove: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineMouseOut: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineMouseOver: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineMouseUp: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() lineRightClick: EventEmitter<google.maps.PolyMouseEvent> = new EventEmitter<google.maps.PolyMouseEvent>();
@Output() polyPathChange = new EventEmitter<MVCEvent<google.maps.LatLng>>();
@ContentChildren(AgmPolylinePoint) points: QueryList<AgmPolylinePoint>;
@ContentChildren(AgmPolylineIcon) iconSequences: QueryList<AgmPolylineIcon>;
private static _polylineOptionsAttributes: string[] = [
'draggable', 'editable', 'visible', 'geodesic', 'strokeColor', 'strokeOpacity', 'strokeWeight',
'zIndex',
];
private _id: string;
private _polylineAddedToManager = false;
private _subscriptions: Subscription[] = [];
constructor(private _polylineManager: PolylineManager) { this._id = (polylineId++).toString(); }
ngAfterContentInit() {
if (this.points.length) {
this.points.forEach((point: AgmPolylinePoint) => {
const s = point.positionChanged.subscribe(
() => { this._polylineManager.updatePolylinePoints(this); });
this._subscriptions.push(s);
});
}
if (!this._polylineAddedToManager) {
this._init();
}
const pointSub = this.points.changes.subscribe(() => this._polylineManager.updatePolylinePoints(this));
this._subscriptions.push(pointSub);
this._polylineManager.updatePolylinePoints(this);
const iconSub = this.iconSequences.changes.subscribe(() => this._polylineManager.updateIconSequences(this));
this._subscriptions.push(iconSub);
}
ngOnChanges(changes: SimpleChanges): any {
if (!this._polylineAddedToManager) {
this._init();
return;
}
const options: {[propName: string]: any} = {};
const optionKeys = Object.keys(changes).filter(
k => AgmPolyline._polylineOptionsAttributes.indexOf(k) !== -1);
optionKeys.forEach(k => options[k] = changes[k].currentValue);
this._polylineManager.setPolylineOptions(this, options);
}
getPath(): Promise<google.maps.LatLng[]> {
return this._polylineManager.getPath(this);
}
private _init() {
this._polylineManager.addPolyline(this);
this._polylineAddedToManager = true;
this._addEventListeners();
}
private _addEventListeners() {
const handlers = [
{name: 'click', handler: (ev: google.maps.PolyMouseEvent) => this.lineClick.emit(ev)},
{name: 'dblclick', handler: (ev: google.maps.PolyMouseEvent) => this.lineDblClick.emit(ev)},
{name: 'drag', handler: (ev: google.maps.MouseEvent) => this.lineDrag.emit(ev)},
{name: 'dragend', handler: (ev: google.maps.MouseEvent) => this.lineDragEnd.emit(ev)},
{name: 'dragstart', handler: (ev: google.maps.MouseEvent) => this.lineDragStart.emit(ev)},
{name: 'mousedown', handler: (ev: google.maps.PolyMouseEvent) => this.lineMouseDown.emit(ev)},
{name: 'mousemove', handler: (ev: google.maps.PolyMouseEvent) => this.lineMouseMove.emit(ev)},
{name: 'mouseout', handler: (ev: google.maps.PolyMouseEvent) => this.lineMouseOut.emit(ev)},
{name: 'mouseover', handler: (ev: google.maps.PolyMouseEvent) => this.lineMouseOver.emit(ev)},
{name: 'mouseup', handler: (ev: google.maps.PolyMouseEvent) => this.lineMouseUp.emit(ev)},
{name: 'rightclick', handler: (ev: google.maps.PolyMouseEvent) => this.lineRightClick.emit(ev)},
];
handlers.forEach((obj) => {
const os = this._polylineManager.createEventObservable(obj.name, this).subscribe(obj.handler);
this._subscriptions.push(os);
});
this._polylineManager.createPathEventObservable(this).then((ob$) => {
const os = ob$.subscribe(pathEvent => this.polyPathChange.emit(pathEvent));
this._subscriptions.push(os);
});
}
_getPoints(): AgmPolylinePoint[] {
if (this.points) {
return this.points.toArray();
}
return [];
}
_getIcons(): Array<AgmPolylineIcon> {
if (this.iconSequences) {
return this.iconSequences.toArray();
}
return [];
}
id(): string { return this._id; }
ngOnDestroy() {
this._polylineManager.deletePolyline(this);
this._subscriptions.forEach((s) => s.unsubscribe());
}
}