From 52188d72335cec26c1668cd81addefc7965f19fe Mon Sep 17 00:00:00 2001 From: "jose.ignacio.fagian" <nachofagian@gmail.com> Date: Fri, 20 Jul 2018 20:23:30 -0300 Subject: [PATCH] Implementacion de barra de controles --- Frontend Angular 4/src/app/app.module.ts | 5 +- .../src/app/layout/layout.module.ts | 2 +- .../plotter/graph3D/graph3D.component.html | 242 +++++++++++++----- .../plotter/graph3D/graph3D.component.scss | 24 +- .../plotter/graph3D/graph3D.component.ts | 70 +++-- .../layout/plotter/graph3D/graph3D.helper.ts | 27 ++ .../layout/plotter/graph3D/graph3D.module.ts | 5 +- Frontend Angular 4/src/app/shared/config.ts | 8 +- .../app/shared/utils/closePopoverDirective.ts | 34 +++ 9 files changed, 326 insertions(+), 91 deletions(-) create mode 100644 Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts diff --git a/Frontend Angular 4/src/app/app.module.ts b/Frontend Angular 4/src/app/app.module.ts index 084f634..51ad01f 100644 --- a/Frontend Angular 4/src/app/app.module.ts +++ b/Frontend Angular 4/src/app/app.module.ts @@ -7,10 +7,11 @@ import { AppComponent } from './app.component'; import { AuthGuard } from './shared/guards/auth.guard'; import { SessionService } from './shared/services/session.service'; import { NotificacionService } from './shared/services/notificacion.service'; -import {NotificacionModule} from './notificacion/notificacion.module' +import {NotificacionModule} from './notificacion/notificacion.module'; + @NgModule({ declarations: [ - AppComponent, + AppComponent ], imports: [ NotificacionModule, diff --git a/Frontend Angular 4/src/app/layout/layout.module.ts b/Frontend Angular 4/src/app/layout/layout.module.ts index 9777481..ab31a0b 100644 --- a/Frontend Angular 4/src/app/layout/layout.module.ts +++ b/Frontend Angular 4/src/app/layout/layout.module.ts @@ -23,7 +23,7 @@ import { NotificacionModule } from '../notificacion/notificacion.module'; declarations: [ LayoutComponent, HeaderComponent, - SidebarComponent + SidebarComponent ], providers: [AuthenticationService, HaskellService] }) diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html index add6d7d..2cbdffc 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html +++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html @@ -1,93 +1,201 @@ <div class="card"> - <div class="controls"> - <div class="btn-group ddown"> - <button - type="button" - class="btn btn-secondary" - style="min-width: 70px;" - (click)=changeZoomType() - > - {{getZoom3DTypeName(zoomType)}} - </button> - <div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown"> - <button class="btn btn-secondary dropdown-toggle-split" ngbDropdownToggle></button> - <div class="dropdown-menu" ngbDropdownMenu> - <button - *ngFor="let type of [1,2,3,4]" - class="dropdown-item" - [disabled]="type === zoomType" - (click)=changeZoomType(type) - > - {{getZoom3DTypeName(type)}} - </button> - </div> - </div> - </div> - + <div class="controls"> + <div class="btn-group ddown"> <button - ngbPopover="Zoom +" - triggers="mouseenter:mouseleave" - data-placement="bottom" - class="btn btn-sm btn-secondary" - (click)=zoomIn() + type="button" + class="btn btn-secondary" + style="min-width: 70px;" + (click)=changeZoomType() > - <i class="fa fa-plus"></i> + {{getZoom3DTypeName(graphProps.zoomType)}} </button> + <div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown"> + <button class="btn btn-secondary dropdown-toggle-split" ngbDropdownToggle></button> + <div class="dropdown-menu" ngbDropdownMenu> + <button + *ngFor="let type of [1,2,3,4]" + class="dropdown-item" + [disabled]="type === graphProps.zoomType" + (click)=changeZoomType(type) + > + {{getZoom3DTypeName(type)}} + </button> + </div> + </div> + </div> - <button - ngbPopover="Zoom -" - triggers="mouseenter:mouseleave" - data-placement="bottom" - class="btn btn-sm btn-secondary" - (click)=zoomOut() - > - <i class="fa fa-minus"></i> - </button> + <button + ngbPopover="Zoom +" + triggers="mouseenter:mouseleave" + data-placement="bottom" + class="btn btn-sm btn-secondary" + (click)=zoomIn() + > + <i class="fa fa-plus"></i> + </button> - <button - ngbPopover="Centrar" - triggers="mouseenter:mouseleave" - data-placement="bottom" - class="btn btn-sm btn-secondary" - (click)=zoomMas() - > - <i class="fa fa-arrows"></i> - </button> + <button + ngbPopover="Zoom -" + triggers="mouseenter:mouseleave" + data-placement="bottom" + class="btn btn-sm btn-secondary" + (click)=zoomOut() + > + <i class="fa fa-minus"></i> + </button> - <button - ngbPopover="Borrar" - triggers="mouseenter:mouseleave" - data-placement="bottom" - class="btn btn-sm btn-secondary" - (click)=zoomMas() - > - <i class="fa fa-trash"></i> - </button> + <button + ngbPopover="Centrar" + triggers="mouseenter:mouseleave" + data-placement="bottom" + class="btn btn-sm btn-secondary" + (click)=center() + > + <i class="fa fa-arrows"></i> + </button> - <button - ngbPopover="Configuración" + <button + closePopoverOnOutsideClick + class="btn btn-sm btn-secondary" + placement="bottom" + [ngbPopover]=popoverAxesSize + popoverTitle="Rango de ejes" + #popover="ngbPopover" + tiggers="click" + > + <i class="fa fa-arrows-h"></i> + </button> + <ng-template #popoverAxesSize> + <div class="axes-size"> + <div class="axe"> + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.xMin" + [max]="graphProps.range.xMax-1" + [min]="-99" + (change)="onChangeAxesSize('xMin', $event)" + /> + <div class="less-than"> + <span>≤</span>x<span>≤</span> + </div> + + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.xMax" + [max]="99" + [min]="graphProps.range.xMin+1" + (change)="onChangeAxesSize('xMax', $event)" + /> + </div> + + <div class="axe"> + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.yMin" + [max]="graphProps.range.yMax-1" + [min]="-99" + (change)="onChangeAxesSize('yMin', $event)" + /> + <div class="less-than"> + <span>≤</span>y<span>≤</span> + </div> + + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.yMax" + [max]="99" + [min]="graphProps.range.yMin+1" + (change)="onChangeAxesSize('yMax', $event)" + /> + </div> + + <div class="axe"> + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.zMin" + [max]="graphProps.range.zMax-1" + [min]="-99" + (change)="onChangeAxesSize('zMin', $event)" + /> + <div class="less-than"> + <span>≤</span>z<span>≤</span> + </div> + + <input + type="number" + class="form-control form-control-sm" + [(ngModel)]="graphProps.range.zMax" + [max]="99" + [min]="graphProps.range.zMin+1" + (change)="onChangeAxesSize('zMax', $event)" + /> + </div> + </div> + </ng-template> + + + <button + ngbPopover="Borrar" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" - (click)=zoomMas() + (click)=clear() + > + <i class="fa fa-trash"></i> + </button> + + <button + [ngbPopover]=popoverConfig + closePopoverOnOutsideClick + placement="bottom" + + tiggers="click" + class="btn btn-sm btn-secondary" + popoverTitle="Configuración" > <i class="fa fa-gear"></i> </button> - + + <ng-template #popoverConfig> + <div style="width: 140px;"> + <label class="d-block"> + <input type="checkbox"[checked]=graphProps.showAxes (click)="changeAxesVisibility()"> + Mostrar grilla + </label> + + <div style="display: flex;"> + <span style="margin-right: 8px; align-self: center;"> + Quality: + </span> + + <input + type="number" + style="width: 55px;" + class="form-control form-control-sm" + /> + </div> + </div> + </ng-template> + + </div> <div class="card-block contenedor-canvas" > <animation-control [minSpeed]="60" - [value]="animation.value" - [speed]="animation.speed" - [visible]="animation.visible" - [playing]="animation.playing" + [value]="animationProps.value" + [speed]="animationProps.speed" + [visible]="animationProps.visible" + [playing]="animationProps.playing" [onChangeSpeed]="onAnimationChangeSpeed" [onTogglePlay]="onAnimationTogglePlay" > </animation-control> - <div #graph3DElement style="width: 100%; height: 100%;"> </div> diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss index 9b83024..fe06fa3 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss +++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss @@ -14,7 +14,25 @@ vertical-align: bottom; button { - padding: 2.5px 5px; + padding: 2.5px 8px 2.5px 3px; + } + } + + .axes-size { + width: 165px; + + .axe { + display: flex; + + &:not(:last-child) { + margin-bottom: 6px; + } + + .less-than { + padding: 0 2.5px 0 5px; + font-size: 17px; + letter-spacing: 4px; + } } } } @@ -22,4 +40,8 @@ .dropdown-item:disabled{ background-color: #f7f7f7; color: #9e9e9e; +} + +.d-block{ + display: block; } \ No newline at end of file diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts index 532dcdd..690432c 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts +++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, ViewChild, ElementRef, NgZone } from '@angular/core'; import * as graph3DLib from 'graph3d'; import { GHCIService } from '../../../shared/services/ghci.service'; -import { formatJSON, AnimationProps, Zoom3DType } from './graph3D.helper'; +import { formatJSON, AnimationProps, Zoom3DType, GraphProps, Default_GraphProps } from './graph3D.helper'; @Component({ selector: 'graph3d-component', @@ -18,16 +18,17 @@ export class Graph3DComponent implements OnInit { @ViewChild('graph3DElement') private graph3DRef: ElementRef; - public zoomType: Zoom3DType = Zoom3DType.Normal; - - private animation : AnimationProps = { + private graphProps : GraphProps = Default_GraphProps; + + private animationProps : AnimationProps = { visible: false, playing: false, value: 0, speed: 1000 }; + - constructor(private ghciService: GHCIService, private zone: NgZone) { + constructor(ghciService: GHCIService, private zone: NgZone) { this.ghciServiceSub = ghciService.messages.subscribe( message => { if (message.tipo == "canvas3D") { @@ -38,12 +39,13 @@ export class Graph3DComponent implements OnInit { else if (message.tipo == "animacion3D") { const frames = message.resultado.map((frame) => JSON.parse(formatJSON(frame))); - this.animation.visible = true; - this.animation.playing = true; - this.animation.value = 0; + this.animationProps.visible = true; + this.animationProps.playing = true; + this.animationProps.value = 0; + graph3DLib.clear(); graph3DLib.initializeAnimation(frames, - (value) => this.animation.value = value + (value) => this.animationProps.value = value ); graph3DLib.playAnimation(); @@ -53,9 +55,9 @@ export class Graph3DComponent implements OnInit { } ngOnInit() { - this.zone.runOutsideAngular(() => { + // this.zone.runOutsideAngular(() => { graph3DLib.initialize(this.graph3DRef.nativeElement); - }) + //}) } ngOnDestroy() { @@ -71,30 +73,52 @@ export class Graph3DComponent implements OnInit { } onAnimationChangeSpeed = (value) => { - this.animation.speed = parseInt(value); + this.animationProps.speed = parseInt(value); graph3DLib.changeSpeedAnimation(parseInt(value)); } onAnimationTogglePlay = () => { - if (this.animation.playing) { + if (this.animationProps.playing) { graph3DLib.pauseAnimation(); } else { graph3DLib.playAnimation(); } - this.animation.playing = !this.animation.playing; + this.animationProps.playing = !this.animationProps.playing; } public changeZoomType = (type: Zoom3DType = null) => { if (type != null) { - this.zoomType = type; + this.graphProps.zoomType = type; } else { - this.zoomType = (this.zoomType % 4) + 1; + this.graphProps.zoomType = (this.graphProps.zoomType % 4) + 1; } - graph3DLib.changeZoomType(this.zoomType); + graph3DLib.changeZoomType(this.graphProps.zoomType); + } + + public changeAxesVisibility = () => { + this.graphProps.showAxes = !this.graphProps.showAxes; + graph3DLib.showAxes(this.graphProps.showAxes); + } + + public onChangeAxesSize = (v, event) => { + let value = this.graphProps.range[v]; + + const min = parseInt(event.target.min); + const max = parseInt(event.target.max); + + if (value < min) { + this.graphProps.range[v] = min; + } + + if (value > max) { + this.graphProps.range[v] = max; + } + + graph3DLib.changeAxesSize(this.graphProps.range) } public zoomIn = () => { @@ -105,6 +129,18 @@ export class Graph3DComponent implements OnInit { graph3DLib.changeZoom(false); } + public clear = () => { + this.animationProps.visible = false; + + graph3DLib.clear(); + } + + public center = () => { + this.graphProps = Default_GraphProps; + + graph3DLib.reset(); + } + public getZoom3DTypeName = (type: Zoom3DType) => { switch (type) { case Zoom3DType.Normal: diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts index a13ebd2..90fc980 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts +++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts @@ -8,6 +8,7 @@ export function formatJSON(jsonString: string) : string { ) } + export interface AnimationProps { visible?: boolean, playing?: boolean, @@ -22,3 +23,29 @@ export enum Zoom3DType { ZAxis, } +export interface GraphProps { + zoomType?: Zoom3DType, + showAxes?: boolean, + range: { + xMin?: number, + xMax?: number, + yMin?: number, + yMax?: number, + zMin?: number, + zMax?: number + } +} + +export const Default_GraphProps : GraphProps = { + zoomType: Zoom3DType.Normal, + showAxes: true, + range: { + xMin: -10, + xMax: 10, + yMin: -10, + yMax: 10, + zMin: -10, + zMax: 10 + } +} + diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts index 0497860..1df9cb3 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts +++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts @@ -5,12 +5,15 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { FormsModule } from '@angular/forms'; import { Graph3DComponent } from './graph3D.component'; import { AnimationControlComponent } from '../animation-control/animation-control.component'; +import { ClosePopoverOnOutsideClickDirective } from '../../../shared/utils/closePopoverDirective'; + @NgModule({ imports: [FormsModule, RouterModule, CommonModule, NgbModule], declarations: [ AnimationControlComponent, - Graph3DComponent + Graph3DComponent, + ClosePopoverOnOutsideClickDirective ], entryComponents: [ AnimationControlComponent diff --git a/Frontend Angular 4/src/app/shared/config.ts b/Frontend Angular 4/src/app/shared/config.ts index 269b083..1100f6f 100644 --- a/Frontend Angular 4/src/app/shared/config.ts +++ b/Frontend Angular 4/src/app/shared/config.ts @@ -5,5 +5,9 @@ //export const GHCI_URL = 'ws://localhost:9090/endpoint'; //Configuracion dinamica pensando en servidor con ip dinamica -export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090'; -export const GHCI_URL = window.location.protocol == 'http:'? 'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint'; + +// export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090'; +// export const GHCI_URL = window.location.protocol == 'http:'? 'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint'; + +export const SERVER = 'http://192.168.95.3:9090'; +export const GHCI_URL = 'ws://192.168.95.3:9090/endpoint'; diff --git a/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts b/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts new file mode 100644 index 0000000..2faa926 --- /dev/null +++ b/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts @@ -0,0 +1,34 @@ +import { Directive, HostListener, ElementRef, ComponentRef } from '@angular/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { NgbPopoverWindow } from '@ng-bootstrap/ng-bootstrap/popover/popover'; + +@Directive({ + selector: '[closePopoverOnOutsideClick][ngbPopover]' +}) +export class ClosePopoverOnOutsideClickDirective { + + constructor(private elementRef: ElementRef, + private ngbPopover: NgbPopover) { + + } + + @HostListener('document:click', ['$event']) + private documentClicked(event: MouseEvent): void { + + // Popover is open + if (this.ngbPopover && this.ngbPopover.isOpen()) { + + // Not clicked on self element + if (!this.elementRef.nativeElement.contains(event.target)) { + + // Hacking typescript to access private member + const popoverWindowRef: ComponentRef<NgbPopoverWindow> = (this.ngbPopover as any)._windowRef; + + // If clicked outside popover window + if (!popoverWindowRef.location.nativeElement.contains(event.target)) { + this.ngbPopover.close(); + } + } + } + } +} \ No newline at end of file -- GitLab