all files / component/mouse-dragdrop/ mouse-droppable.directive.ts

80.7% Statements 46/57
50% Branches 15/30
91.67% Functions 11/12
79.25% Lines 42/53
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                            40×     111×           40× 40×   40×   40×   40× 42× 42×                                                                           40×                    
/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
 
import { Directive, ElementRef, Input, OnDestroy } from '@angular/core';
import { from as observableFrom, Observable } from 'rxjs';
import { filter, first, takeUntil, takeWhile } from 'rxjs/operators';
import { Position } from '../../common/core/graphics/position';
import { Rect } from '../../common/core/graphics/rect';
import { DejaMouseDragDropService, IDragCursorInfos, IDragDropContext, IDropCursorInfos } from './mouse-dragdrop.service';
 
@Directive({
    selector: '[deja-mouse-droppable]',
})
export class DejaMouseDroppableDirective implements OnDestroy {
    private _context: IDejaMouseDroppableContext;
    private _dragContext: IDragDropContext;
    private isAlive = true;
 
    @Input('deja-mouse-droppable')
    public set context(value: IDejaMouseDroppableContext) {
        this._context = value;
    }
 
    public get context() {
        return this._context;
    }
 
    constructor(elementRef: ElementRef, dragDropService: DejaMouseDragDropService) {
        const element = elementRef.nativeElement as HTMLElement;
 
        const dragging$ = observableFrom(dragDropService.dragging$);
 
        const kill$ = dragging$.pipe(
            filter((value) => !value));
 
        dragging$.pipe(
            takeWhile(() => this.isAlive),
            filter((value) => value))
            .subscribe(() => {
                kill$.pipe(
                    first())
                    .subscribe(() => {
                        Eif (this._dragContext) {
                            Eif (this.context && this.context.drop) {
                                this.context.drop(this._dragContext);
                            }
                            this._dragContext = undefined;
                        }
                        dragDropService.dropCursor$.next(undefined);
                    });
 
                observableFrom(dragDropService.dragCursor$).pipe(
                    takeUntil(kill$))
                    .subscribe((dragCursor) => {
                        const bounds = new Rect(element.getBoundingClientRect());
                        if (this.context && dragCursor) {
                            const { pageX, pageY } = dragCursor.originalEvent;
                            if (bounds.containsPoint(new Position(pageX, pageY))) {
                                Eif (!this._dragContext) {
                                    this._dragContext = dragDropService.context;
                                    Eif (this.context.dragEnter) {
                                        const dropContext = this.context.dragEnter(this._dragContext, dragCursor);
                                        Eif (dropContext) {
                                            const dropContextObs = dropContext as Observable<IDropCursorInfos>;
                                            Iif (dropContextObs.subscribe) {
                                                // Observable
                                                dropContextObs.pipe(
                                                    first())
                                                    .subscribe((cursor) => {
                                                        dragDropService.dropCursor$.next(cursor);
                                                    });
                                                return;
                                            } else {
                                                dragDropService.dropCursor$.next(dropContext as IDropCursorInfos);
                                            }
                                        }
                                    }
                                } else if (this.context.dragOver) {
                                    const overContext = this.context.dragOver(this._dragContext, dragCursor);
                                    if (overContext) {
                                        dragDropService.dropCursor$.next(overContext);
                                    }
                                }
                            } else Iif (this._dragContext) {
                                if (this.context && this.context.dragLeave) {
                                    this.context.dragLeave(this._dragContext);
                                }
                                this._dragContext = undefined;
                                dragDropService.dropCursor$.next(undefined);
                            }
                        }
                    });
            });
    }
 
    public ngOnDestroy() {
        this.isAlive = false;
    }
}
 
export interface IDejaMouseDroppableContext {
    dragEnter?(dragContext: IDragDropContext, dragCursor: IDragCursorInfos): IDropCursorInfos | Observable<IDropCursorInfos>; // Return object or observable<object>
    dragOver?(dragContext: IDragDropContext, dragCursor: IDragCursorInfos): IDropCursorInfos;
    dragLeave?(dragContext: IDragDropContext): void;
    drop?(dragContext: IDragDropContext): void;
}