File
Implements
Metadata
selector |
app-effects-creator |
styleUrls |
app-effects-creator.component.css |
templateUrl |
./app-effects-creator.component.html |
Methods
createEffect
|
createEffect()
|
|
|
isDefined
|
isDefined(something: )
|
|
Parameters :
Name |
Optional |
something |
No
|
|
removeEffect
|
removeEffect()
|
|
|
resetRemove
|
resetRemove()
|
|
|
updateEffect
|
updateEffect(effect: )
|
|
|
updateRemovableEffects
|
updateRemovableEffects()
|
|
|
defaultStep
|
defaultStep: number
|
Type : number
|
Default value : 0.01
|
|
effects
|
effects: any
|
Type : any
|
|
effectsCreatorArray
|
effectsCreatorArray: any
|
Type : any
|
|
effectStruct
|
effectStruct: any
|
Type : any
|
|
JSON
|
JSON:
|
Default value : JSON
|
|
removableEffects
|
removableEffects:
|
|
selectedEffectRemove
|
selectedEffectRemove: string
|
Type : string
|
|
selectedEffects
|
selectedEffects:
|
|
validName
|
validName:
|
Default value : false
|
|
import { Component, OnInit } from '@angular/core';
import { EffectsService } from '../../services/effects.service';
import { FormBuilder, FormGroup, AbstractControl, Validators, ValidatorFn } from '@angular/forms';
import { PlayerService } from 'src/app/services/player.service';
import { effectsCreatorArray } from 'src/app/data/effectsCreator';
@Component({
selector: 'app-effects-creator',
templateUrl: './app-effects-creator.component.html',
styleUrls: ['./app-effects-creator.component.css']
})
export class AppEffectsCreatorComponent implements OnInit {
effectsCreatorArray: any;
effects: any;
selectedEffect: string;
selectedEffectRemove: string;
effectStruct: any;
JSON = JSON;
config: FormGroup;
name = '';
validName = false;
defaultStep = 0.01;
selectedEffects;
removableEffects;
constructor(private effectServ: EffectsService, private builder: FormBuilder, private playerServ: PlayerService) {
this.effectsCreatorArray = effectsCreatorArray;
this.effects = this.effectServ.getEffects();
}
updateRemovableEffects() {
this.removableEffects = this.effects.filter(effect => {
return this.selectedEffects.indexOf(effect.id) === -1;
});
}
ngOnInit() {
this.selectedEffects = [
...this.playerServ.effects[0].map(effect => effect.id),
...this.playerServ.effects[1].map(effect => effect.id)
];
this.updateRemovableEffects();
}
updateEffect(effect) {
this.effectStruct = JSON.parse(effect);
const config = {};
for (const actualConfig of this.effectStruct.configs) {
if (this.isDefined(actualConfig.min)) {
config[actualConfig.name] = [
actualConfig.default,
[
Validators.required,
Validators.min(actualConfig.min),
Validators.max(actualConfig.max),
stepValidator(actualConfig.step ? actualConfig.step : this.defaultStep)
]
];
}
if (this.isDefined(actualConfig.values)) {
config[actualConfig.name] = actualConfig.default;
}
if (this.isDefined(actualConfig.value)) {
config[actualConfig.name] = actualConfig.value;
}
}
this.config = this.builder.group(config);
}
reset() {
this.selectedEffect = null;
this.effectStruct = null;
}
resetRemove() {
this.updateRemovableEffects();
this.selectedEffectRemove = null;
}
isDefined(something) {
return typeof something !== 'undefined';
}
createEffect() {
if (this.validName && this.config.valid) {
this.effectServ.addEffect({
name: this.name,
type: this.effectStruct.name,
active: false,
config: this.config.value
});
this.effects = this.effectServ.getEffects();
this.reset();
this.updateRemovableEffects();
}
}
checkName() {
if (
!this.effects.find(
effect =>
effect.name
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '') ===
this.name
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
)
) {
this.validName = true;
} else {
this.validName = false;
}
}
removeEffect() {
this.effectServ.removeEffect(this.selectedEffectRemove);
this.effects = this.effectServ.getEffects();
this.resetRemove();
}
}
function stepValidator(step: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null => {
// decimalAdjust is needed because of js clunky floating point maths
const forbidden = decimalAdjust('round', control.value / step, -5) % 1 !== 0;
return forbidden ? { 'forbidden number step': { value: control.value } } : null;
};
}
function decimalAdjust(type, value, exp) {
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? +value[1] - exp : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? +value[1] + exp : exp));
}
<!--
This file is part of Web Virtual DJ.
Web Virtual DJ is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Web Virtual DJ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Web Virtual DJ. If not, see <https://www.gnu.org/licenses/>.
-->
<div class="settings-container" id="app_effects_creator">
<div class="question-container">
<div class="question">
<div class="question-label">{{ 'EFFCREATOR.CREATE' | translate }}</div>
<select [(ngModel)]="selectedEffect" (ngModelChange)="updateEffect($event)">
<option *ngFor="let effect of effectsCreatorArray" [value]="JSON.stringify(effect)"
title="{{effect.description}}">{{effect.name}}</option>
</select>
</div>
</div>
<div *ngIf="effectStruct">
<div class="question">
<div class="question-label">{{effectStruct.name}}</div>
{{effectStruct.description}}
</div>
<div class="question" style="width:250px">
<p style="margin: 0px 5px 5px 0px;">{{ 'EFFCREATOR.NAME' | translate }}</p>
<input type="text" [(ngModel)]="name" (ngModelChange)="checkName()"
[title]="'At least '+ nameChars+' characters'">
</div>
<div class="question">
<div class="question-label">{{ 'EFFCREATOR.CONFIG' | translate }}</div>
</div>
<div class="question">
<table [formGroup]="config">
<tr *ngFor="let config of effectStruct.configs;let j=index" style="height:40px;">
<td
[attr.title]="isDefined(config.min)?'A value between '+config.min+' and '+config.max+' in steps of '+(config.step?config.step:defaultStep):null">
{{config.name}}:</td>
<td>
<input *ngIf="isDefined(config.min)" style="width: 100%" type="number" [formControlName]="config.name"
[min]="config.min" [max]="config.max" [step]="config.step?config.step:defaultStep"
[attr.title]="'A value between '+config.min+' and '+config.max+' in steps of '+(config.step?config.step:defaultStep)">
<select *ngIf="isDefined(config.values)" [formControlName]="config.name">
<option *ngFor="let value of config.values" [value]="value">{{value}}</option>
</select>
<div *ngIf="isDefined(config.value)">{{config.value}}</div>
</td>
</tr>
</table>
</div>
<button (click)="createEffect()" [disabled]="!validName || !config.valid">{{ 'EFFCREATOR.CREATEBUTTON' | translate
}}</button>
</div>
<div class="question">
<div class="question-label">{{ 'EFFCREATOR.REMOVE' | translate }}</div>
<div *ngIf="!(effects.length>6 && removableEffects.length)">{{ 'EFFCREATOR.TOREMOVE' | translate }}</div>
<select *ngIf="effects.length>6 && removableEffects.length" [(ngModel)]="selectedEffectRemove" style="width:250px">
<option *ngFor="let effect of removableEffects" [value]="effect.id">{{effect.name}}</option>
</select>
<button *ngIf="effects.length>6" style="width:250px" (click)="removeEffect()" [disabled]="">{{
'EFFCREATOR.REMOVEBUTTON' | translate }}</button>
</div>
</div>