import {
Directive,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChange,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { RectangleManager } from '../services/managers/rectangle-manager';
@Directive({
selector: 'agm-rectangle',
})
export class AgmRectangle implements OnInit, OnChanges, OnDestroy {
@Input() north: number;
@Input() east: number;
@Input() south: number;
@Input() west: number;
@Input() clickable = true;
@Input('rectangleDraggable') draggable = false;
@Input() editable = false;
@Input() fillColor: string;
@Input() fillOpacity: number;
@Input() strokeColor: string;
@Input() strokeOpacity: number;
@Input() strokePosition: keyof typeof google.maps.StrokePosition = 'CENTER';
@Input() strokeWeight = 0;
@Input() visible = true;
@Input() zIndex: number;
@Output()
boundsChange: EventEmitter<google.maps.LatLngBoundsLiteral> = new EventEmitter<
google.maps.LatLngBoundsLiteral
>();
@Output()
rectangleClick: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
rectangleDblClick: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() drag: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() dragEnd: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
dragStart: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
mouseDown: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
mouseMove: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() mouseOut: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
mouseOver: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output() mouseUp: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
@Output()
rightClick: EventEmitter<google.maps.MouseEvent> = new EventEmitter<google.maps.MouseEvent>();
private _rectangleAddedToManager = false;
private static _mapOptions: string[] = [
'fillColor',
'fillOpacity',
'strokeColor',
'strokeOpacity',
'strokePosition',
'strokeWeight',
'visible',
'zIndex',
'clickable',
];
private _eventSubscriptions: Subscription[] = [];
constructor(private _manager: RectangleManager) {}
ngOnInit() {
this._manager.addRectangle(this);
this._rectangleAddedToManager = true;
this._registerEventListeners();
}
ngOnChanges(changes: { [key: string]: SimpleChange }) {
if (!this._rectangleAddedToManager) {
return;
}
if (
changes['north'] ||
changes['east'] ||
changes['south'] ||
changes['west']
) {
this._manager.setBounds(this);
}
if (changes['editable']) {
this._manager.setEditable(this);
}
if (changes['draggable']) {
this._manager.setDraggable(this);
}
if (changes['visible']) {
this._manager.setVisible(this);
}
this._updateRectangleOptionsChanges(changes);
}
private _updateRectangleOptionsChanges(changes: {
[propName: string]: SimpleChange;
}) {
const options: google.maps.RectangleOptions = {};
const optionKeys = Object.keys(changes).filter(
k => AgmRectangle._mapOptions.indexOf(k) !== -1,
);
optionKeys.forEach(k => {
options[k] = changes[k].currentValue;
});
if (optionKeys.length > 0) {
this._manager.setOptions(this, options);
}
}
private _registerEventListeners() {
const events: Map<string, EventEmitter<any>> = new Map<
string,
EventEmitter<any>
>();
events.set('bounds_changed', this.boundsChange);
events.set('click', this.rectangleClick);
events.set('dblclick', this.rectangleDblClick);
events.set('drag', this.drag);
events.set('dragend', this.dragEnd);
events.set('dragStart', this.dragStart);
events.set('mousedown', this.mouseDown);
events.set('mousemove', this.mouseMove);
events.set('mouseout', this.mouseOut);
events.set('mouseover', this.mouseOver);
events.set('mouseup', this.mouseUp);
events.set('rightclick', this.rightClick);
events.forEach((eventEmitter, eventName) => {
this._eventSubscriptions.push(
this._manager
.createEventObservable<google.maps.MouseEvent>(eventName, this)
.subscribe(value => {
switch (eventName) {
case 'bounds_changed':
this._manager.getBounds(this).then(bounds =>
eventEmitter.emit({
north: bounds.getNorthEast().lat(),
east: bounds.getNorthEast().lng(),
south: bounds.getSouthWest().lat(),
west: bounds.getSouthWest().lng(),
} as google.maps.LatLngBoundsLiteral),
);
break;
default:
eventEmitter.emit(value);
}
}),
);
});
}
ngOnDestroy() {
this._eventSubscriptions.forEach(s => s.unsubscribe());
this._eventSubscriptions = null;
this._manager.removeRectangle(this);
}
getBounds(): Promise<google.maps.LatLngBounds> {
return this._manager.getBounds(this);
}
}