import {Component, ElementRef, ViewChild} from '@angular/core'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {MatButtonModule} from '@angular/material/button'; import {MatInputModule} from '@angular/material/input'; import {MatFormFieldModule} from '@angular/material/form-field'; import {MatSelectModule} from '@angular/material/select'; import {MatSliderModule} from '@angular/material/slider'; import {MatCheckboxModule} from '@angular/material/checkbox'; import {MatTabsModule} from '@angular/material/tabs'; import {MatCardModule} from '@angular/material/card'; import {MatIconModule} from '@angular/material/icon'; import {HeaderComponent} from '@header/header.component'; // Services import {IntersectionPlaneService} from './services/intersection-plane.service'; import {ParticleManagerService} from './services/particle-manager.service'; // Models import {PropertiesComponent} from './components/properties/properties.component'; import {ParticleComponent} from './components/particle/particle.component'; import {FramesComponent} from './components/frames/frames.component'; import {MatSnackBar} from '@angular/material/snack-bar'; import {RenderContainerComponent} from './components/render-container/render-container.component'; import {ParticlesService} from '@api'; @Component({ selector: 'app-particles', standalone: true, imports: [ FormsModule, ReactiveFormsModule, MatButtonModule, MatInputModule, MatFormFieldModule, MatSelectModule, MatSliderModule, MatCheckboxModule, MatTabsModule, MatCardModule, MatIconModule, HeaderComponent, PropertiesComponent, ParticleComponent, FramesComponent, RenderContainerComponent ], templateUrl: './particles.component.html', styleUrl: './particles.component.scss' }) export class ParticlesComponent { @ViewChild('planeSlider') planeSlider!: ElementRef; constructor( private intersectionPlaneService: IntersectionPlaneService, private particleManagerService: ParticleManagerService, private matSnackBar: MatSnackBar, private particlesService: ParticlesService, ) { } /** * Update plane position based on slider */ public updatePlanePosition(event: Event): void { const slider = event.target as HTMLInputElement; const value = Number(slider.value); this.intersectionPlaneService.updatePlanePosition(value); } /** * Get the current plane position */ public get planePosition(): number { return this.intersectionPlaneService.getPlanePosition(); } public set planePosition(newPlanePosition: number) { this.intersectionPlaneService.updatePlanePosition(newPlanePosition); } public get maxOffset(): number { return this.intersectionPlaneService.getMaxOffset(); } public get minOffset(): number { return this.intersectionPlaneService.getMinOffset(); } /** * Generate JSON output */ public generateJson(): string { return this.particleManagerService.generateJson(); } public getJsonFile(): Blob { const jsonContent = this.generateJson(); return new Blob([jsonContent], {type: 'application/json'}); } public saveJsonToFile(): void { const jsonContent = this.generateJson(); const blob = new Blob([jsonContent], {type: 'application/json'}); const url = window.URL.createObjectURL(blob); // Create a temporary link element const a = document.createElement('a'); a.href = url; a.download = 'particle-data.json'; // Append to the document, click it, and remove it document.body.appendChild(a); a.click(); // Clean up window.URL.revokeObjectURL(url); document.body.removeChild(a); this.matSnackBar.open('JSON file downloaded', '', {duration: 2000}); } public copyJson() { navigator.clipboard.writeText(this.generateJson()).then(() => { this.matSnackBar.open('Copied to clipboard', '', {duration: 2000}) }); //TODO validation this.particlesService.saveFile(this.particleManagerService.getParticleData().particle_name, this.getJsonFile()); } }