diff --git a/Frontend Angular 4/src/app/app.module.ts b/Frontend Angular 4/src/app/app.module.ts index 7cac3deb343446316fb9671c625072fa24869fb5..51ad01f17fe31eb997e7f6d9d12614e283de2a74 100755 --- a/Frontend Angular 4/src/app/app.module.ts +++ b/Frontend Angular 4/src/app/app.module.ts @@ -7,11 +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 9777481aaa12a918ec469c807b12d4c1338c7cc5..ab31a0b0ed8846dc4d4c027eafd5e409384201e8 100755 --- 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/matefun/codemirror/matefun-mode-EN.js b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-EN.js new file mode 100644 index 0000000000000000000000000000000000000000..7bf015b380048b83c878b197b18d47e0c5931b4b --- /dev/null +++ b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-EN.js @@ -0,0 +1,258 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("codemirror/lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["codemirror/lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("matefun-EN", function(_config, modeConfig) { + + function switchState(source, setState, f) { + setState(f); + return f(source, setState); + } + + var smallRE = /[a-z_]/; + var largeRE = /[A-Z]/; + var digitRE = /\d/; + var hexitRE = /[0-9A-Fa-f]/; + var octitRE = /[0-7]/; + var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/; + var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/; + var specialRE = /[(),;[\]`{}]/; + var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer + + function normal(source, setState) { + if (source.eatWhile(whiteCharRE)) { + return null; + } + + var ch = source.next(); + if (specialRE.test(ch)) { + if (ch == '{' && source.eat('-')) { + var t = "comment"; + if (source.eat('#')) { + t = "meta"; + } + return switchState(source, setState, ncomment(t, 1)); + } + return null; + } + + if (ch == '\'') { + if (source.eat('\\')) { + source.next(); // should handle other escapes here + } + else { + source.next(); + } + if (source.eat('\'')) { + return "string"; + } + return "string error"; + } + + if (ch == '"') { + return switchState(source, setState, stringLiteral); + } + + if (largeRE.test(ch)) { + source.eatWhile(idRE); + if (source.eat('.')) { + return "qualifier"; + } + return "variable-2"; + } + + if (smallRE.test(ch)) { + source.eatWhile(idRE); + return "variable"; + } + + if (digitRE.test(ch)) { + if (ch == '0') { + if (source.eat(/[xX]/)) { + source.eatWhile(hexitRE); // should require at least 1 + return "integer"; + } + if (source.eat(/[oO]/)) { + source.eatWhile(octitRE); // should require at least 1 + return "number"; + } + } + source.eatWhile(digitRE); + var t = "number"; + if (source.match(/^\.\d+/)) { + t = "number"; + } + if (source.eat(/[eE]/)) { + t = "number"; + source.eat(/[-+]/); + source.eatWhile(digitRE); // should require at least 1 + } + return t; + } + + if (ch == "." && source.eat(".")) + return "keyword"; + + if (symbolRE.test(ch)) { + if (ch == '-' && source.eat(/-/)) { + source.eatWhile(/-/); + if (!source.eat(symbolRE)) { + source.skipToEnd(); + return "comment"; + } + } + var t = "variable"; + if (ch == ':') { + t = "variable-2"; + } + source.eatWhile(symbolRE); + return t; + } + + return "error"; + } + + function ncomment(type, nest) { + if (nest == 0) { + return normal; + } + return function(source, setState) { + var currNest = nest; + while (!source.eol()) { + var ch = source.next(); + if (ch == '{' && source.eat('-')) { + ++currNest; + } + else if (ch == '-' && source.eat('}')) { + --currNest; + if (currNest == 0) { + setState(normal); + return type; + } + } + } + setState(ncomment(type, currNest)); + return type; + }; + } + + function stringLiteral(source, setState) { + while (!source.eol()) { + var ch = source.next(); + if (ch == '"') { + setState(normal); + return "string"; + } + if (ch == '\\') { + if (source.eol() || source.eat(whiteCharRE)) { + setState(stringGap); + return "string"; + } + if (source.eat('&')) { + } + else { + source.next(); // should handle other escapes here + } + } + } + setState(normal); + return "string error"; + } + + function stringGap(source, setState) { + if (source.eat('\\')) { + return switchState(source, setState, stringLiteral); + } + source.next(); + setState(normal); + return "error"; + } + + + var wellKnownWords = (function() { + var wkw = {}; + function setType(t) { + return function () { + for (var i = 0; i < arguments.length; i++) + wkw[arguments[i]] = t; + }; + } + + setType("keyword")( + "include" + ,"set","in" + ,"if", "or" + ,"isEmpty"); + + setType("keyword")("<-", "->"); + + setType("builtin")("-", "+", "*", "/","^","!",":","==","/=","<",">","<=",">=","::","->","X","|"); + + //tipos predefinidos + setType("builtin")("Red", "Green", "Blue", "Black","White","Gray","Yellow","FigEmpty", "[]" + ,"R", "Fig", "Fig3D", "Color", "color3D", "join3D", "rotate3D", "move3D" + ); + + setType("builtin")( + "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf", + "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling", + "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", + "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", + "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", + "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", + "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap", + "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", + "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents", + "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized", + "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", + "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map", + "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound", + "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or", + "otherwise", "pi", "pred", "print", "product", "properFraction", + "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", + "readIO", "readList", "readLn", "readParen", "reads", "readsPrec", + "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse", + "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", + "sequence", "sequence_", "show", "showChar", "showList", "showParen", + "showString", "shows", "showsPrec", "significand", "signum", "sin", + "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum", + "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger", + "toRational", "truncate", "uncurry", "undefined", "unlines", "until", + "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", + "zip3", "zipWith", "zipWith3"); + + var override = modeConfig.overrideKeywords; + if (override) for (var word in override) if (override.hasOwnProperty(word)) + wkw[word] = override[word]; + + return wkw; + })(); + + + + return { + startState: function () { return { f: normal }; }, + copyState: function (s) { return { f: s.f }; }, + + token: function(stream, state) { + var t = state.f(stream, function(s) { state.f = s; }); + var w = stream.current(); + return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t; + }, + + blockCommentStart: "{-", + blockCommentEnd: "-}", + lineComment: "--" + }; + +}); + +CodeMirror.defineMIME("text/x-matefun", "matefun-EN"); + +}); \ No newline at end of file diff --git a/Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js similarity index 98% rename from Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js rename to Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js index 04de0e3657f5f1974083586be914cdcacbd91f82..72c0d89e0c93de1b29bda44673535033def1987e 100755 --- a/Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js +++ b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js @@ -8,7 +8,7 @@ })(function(CodeMirror) { "use strict"; - CodeMirror.defineMode("matefun", function(_config, modeConfig) { + CodeMirror.defineMode("matefun-ES", function(_config, modeConfig) { function switchState(source, setState, f) { setState(f); @@ -256,6 +256,6 @@ }); -CodeMirror.defineMIME("text/x-matefun", "matefun"); +CodeMirror.defineMIME("text/x-matefun", "matefun-ES"); }); \ No newline at end of file diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts index ac12c4a9e3fb1d881e30409af5e08edd6ebdcadd..cbd3981ffcfb5b69202e6fdbec347c2dbfd97591 100755 --- a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts +++ b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts @@ -40,7 +40,8 @@ import 'codemirror/addon/search/matchesonscrollbar'; import 'codemirror/addon/search/jump-to-line'; import 'codemirror/addon/edit/matchbrackets'; -import './codemirror-matefun-mode.js' +import './codemirror/matefun-mode-ES.js' +import './codemirror/matefun-mode-EN.js' var codeMirrorRef:any; var componentRef : any; @@ -80,7 +81,7 @@ export class MateFunComponent { matchBrackets: true, extraKeys: {"Ctrl-Space": "autocomplete"}, mode: { - name: "matefun", + name: "matefun-EN", globalVars: true }, gutters: ["CodeMirror-linenumbers", "breakpoints"], 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 add6d7dd261f15de139eaca8227babb68c7d6381..4a6e68d041853e4501fe637ffd157e2e8abc5bcc 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,205 @@ <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" + class="form-control form-control-sm" + [(ngModel)]="graphProps.quality" + [max]="99" + [min]="2" + (change)="onChangeQuality()" + style="width: 55px;" + /> + </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 9b83024218ee13a319457d3e9af18e2f1092e8f9..fe06fa38773fd14c43c00fb1628da017e7846297 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 532dcdd28606ab972dd90b7152efb8d298198cf1..f4713fcba3a9a2059f71c0b40a67e376a52e6389 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, debounce } from './graph3D.helper'; @Component({ selector: 'graph3d-component', @@ -11,23 +11,24 @@ import { formatJSON, AnimationProps, Zoom3DType } from './graph3D.helper'; '(window:resize)': 'onResize($event)' } }) -export class Graph3DComponent implements OnInit { +export class Graph3DComponent { private ghciServiceSub: any; @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(); @@ -52,10 +54,10 @@ export class Graph3DComponent implements OnInit { ) } - ngOnInit() { - this.zone.runOutsideAngular(() => { + ngAfterViewInit() { + // this.zone.runOutsideAngular(() => { graph3DLib.initialize(this.graph3DRef.nativeElement); - }) + //}) } ngOnDestroy() { @@ -71,30 +73,76 @@ 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.graphProps.zoomType = (this.graphProps.zoomType % 4) + 1; + } + + graph3DLib.changeZoomType(this.graphProps.zoomType); + } + + public changeAxesVisibility = () => { + this.graphProps.showAxes = !this.graphProps.showAxes; + graph3DLib.showAxes(this.graphProps.showAxes); + } + + handleAxesRangeDebounced = debounce(function () { + setTimeout(() => + graph3DLib.changeAxesSize(this.graphProps.range) + ); + }, 500); + + public onChangeAxesSize = (v, event) => { + let value = this.graphProps.range[v]; + + const min = parseInt(event.target.min); + const max = parseInt(event.target.max); + + if (value == null) { + value = v.search('Min') ? min : max; + this.graphProps.range[v] = value; + } + + if (value < min) { + this.graphProps.range[v] = min; + } + + if (value > max) { + this.graphProps.range[v] = max; + } + this.handleAxesRangeDebounced(); + //graph3DLib.changeAxesSize(this.graphProps.range) + } + + public onChangeQuality = () => { + const value = this.graphProps.quality; + + if (value == null || value <= 1) { + this.graphProps.quality = 30; } else { - this.zoomType = (this.zoomType % 4) + 1; + this.graphProps.quality = value; } - graph3DLib.changeZoomType(this.zoomType); + graph3DLib.changeOptions({quality: value}); } public zoomIn = () => { @@ -105,6 +153,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 a13ebd2ae34cd8178453a508a3889358d621496a..eef025d8a8d6ce443b8ab15c0f95479e566f9046 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 @@ -1,13 +1,21 @@ export function formatJSON(jsonString: string) : string { const regexRot = /\"rot\"\:\((\d*.\d*),(\d*.\d*),(\d*.\d*)\)/g; + const regexPts = /\"pts\"\:\[\((\-?\d*.\d*),(\-?\d*.\d*),(\-?\d*.\d*)\),\((\-?\d*.\d*),(\-?\d*.\d*),(\-?\d*.\d*)\)\]/g; - return jsonString.replace( - regexRot, (match, x, y, z) => { - return `"rot": { "x": ${x}, "y": ${y}, "z": ${z} }` - } - ) + return jsonString + .replace( + regexRot, (match, x, y, z) => { + return `"rot": { "x": ${x}, "y": ${y}, "z": ${z} }` + } + ) + .replace( + regexPts, (match, x1, y1, z1, x2, y2, z2) => { + return `"pts": [{ "x": ${x1}, "y": ${y1}, "z": ${z1} },{ "x": ${x2}, "y": ${y2}, "z": ${z2} }]` + } + ) } + export interface AnimationProps { visible?: boolean, playing?: boolean, @@ -22,3 +30,42 @@ export enum Zoom3DType { ZAxis, } +export interface GraphProps { + zoomType?: Zoom3DType, + showAxes?: boolean, + quality?: number, + range: { + xMin?: number, + xMax?: number, + yMin?: number, + yMax?: number, + zMin?: number, + zMax?: number + } +} + +export const Default_GraphProps : GraphProps = { + zoomType: Zoom3DType.Normal, + showAxes: true, + quality: 30, + range: { + xMin: -10, + xMax: 10, + yMin: -10, + yMax: 10, + zMin: -10, + zMax: 10 + } +} + +export function debounce(fn, delay) { + var timer = null; + return function () { + var context = this, args = arguments; + clearTimeout(timer); + timer = setTimeout(function () { + fn.apply(context, args); + }, delay); + }; +} + 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 04978608b7acb8ae9599aaecf7864c5c8bcbcf26..1df9cb3ac17e699be6577bd704445c58701a6023 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 85af34a7927b7193fcd816725361aa4465e248eb..970a385ea5a95fdc0c8f623e08d4d760b19996a0 100755 --- a/Frontend Angular 4/src/app/shared/config.ts +++ b/Frontend Angular 4/src/app/shared/config.ts @@ -4,12 +4,15 @@ //export const SERVER = 'http://localhost:9090'; //export const GHCI_URL = 'ws://localhost:9090/endpoint'; -export const SERVER = 'http://localhost:8080'; -export const GHCI_URL = 'ws://localhost:8080/endpoint'; +//export const SERVER = 'http://localhost:8080'; +//export const GHCI_URL = 'ws://localhost:8080/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 = 'http://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090'; -//export const GHCI_URL = 'ws://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090/endpoint'; \ No newline at end of file +// 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'; + +// Google cloud platform +export const SERVER = 'http://35.199.110.129:9090'; +export const GHCI_URL = 'ws://35.199.110.129:9090/endpoint'; + diff --git a/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts b/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed62e5eb702ba84bf84643313f102e44ad40248c --- /dev/null +++ b/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts @@ -0,0 +1,28 @@ +//export const SERVER = 'https://matefun.mybluemix.net'; +//export const GHCI_URL = 'wss://matefun.mybluemix.net/endpoint'; + +//export const SERVER = 'http://localhost:9090'; +//export const GHCI_URL = 'ws://localhost:9090/endpoint'; + +export const SERVER = 'http://localhost:8080'; +export const GHCI_URL = 'ws://localhost:8080/endpoint'; + +//Configuracion dinamica pensando en servidor con ip dinamica +<<<<<<< HEAD +//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://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090'; +//export const GHCI_URL = 'ws://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090/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'; + +export const SERVER = 'http://35.199.110.129:9090'; +export const GHCI_URL = 'ws://35.199.110.129:9090/endpoint'; + +>>>>>>> feature/3DComponentInitialization 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 0000000000000000000000000000000000000000..2faa9261792d65e5938fe733a99a583f498e44b5 --- /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