Removable footer, compact styling for particle creator

This commit is contained in:
2025-12-27 21:04:55 +01:00
parent d1ff7b3f88
commit d9b60d8a94
13 changed files with 175 additions and 195 deletions
@@ -1,12 +1,27 @@
<div class="card-div">
<mat-card>
<mat-card-header>
<mat-card-title>Frames</mat-card-title>
<mat-card-header class="frame-header-fullwidth">
<div class="frame-header-row" mat-card-title>
<span class="frame-title-text">Frames</span>
<div>
<ng-content></ng-content>
<button mat-icon-button color="warn" (click)="removeFrame(currentFrame)"
matTooltip="Delete {{currentFrame}}"
[disabled]="frames.length <= 1">
<mat-icon [class.can-delete]="frames.length > 1" [class.can-not-delete]="frames.length <= 1">
delete
</mat-icon>
</button>
<button mat-icon-button (click)="addFrame()" matTooltip="Add Frame">
<mat-icon class="add-button">add</mat-icon>
</button>
</div>
</div>
</mat-card-header>
<mat-card-content>
<div class="frames-container">
<mat-tab-group [selectedIndex]="frames.indexOf(currentFrame)"
(selectedIndexChange)="switchFrame(frames[$event])">
(selectedIndexChange)="switchFrame(frames[$event])">
@for (frameId of frames; track frameId) {
<mat-tab [label]="frameId">
<div class="frame-content">
@@ -33,21 +48,10 @@
</div>
}
</div>
<div class="frame-actions">
<button mat-raised-button color="warn" (click)="removeFrame(frameId)"
[disabled]="frames.length <= 1">
Remove Frame
</button>
</div>
</div>
</mat-tab>
}
</mat-tab-group>
<div class="add-frame">
<button mat-raised-button color="primary" (click)="addFrame()">
Add New Frame
</button>
</div>
</div>
</mat-card-content>
</mat-card>
@@ -6,6 +6,36 @@
padding: 15px;
}
:host ::ng-deep .mat-mdc-card-header-text {
width: 90%;
text-align: center;
}
.frame-header-row {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.frame-title-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.add-button {
color: green
}
.can-delete {
color: red;
}
.can-not-delete {
color: gray;
}
.particles-list {
height: 550px;
overflow-y: auto;
@@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FramesComponent } from './frames.component';
describe('FramesComponent', () => {
let component: FramesComponent;
let fixture: ComponentFixture<FramesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FramesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(FramesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,5 +1,5 @@
import {Component} from '@angular/core';
import {MatButton, MatIconButton} from "@angular/material/button";
import {Component, inject} from '@angular/core';
import {MatIconButton} from "@angular/material/button";
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card";
import {MatTab, MatTabGroup} from "@angular/material/tabs";
@@ -7,11 +7,11 @@ import {ParticleData} from '../../models/particle.model';
import {MatIcon} from '@angular/material/icon';
import {ParticleManagerService} from '../../services/particle-manager.service';
import {FrameManagerService} from '../../services/frame-manager.service';
import {MatTooltipModule} from '@angular/material/tooltip';
@Component({
selector: 'app-frames',
imports: [
MatButton,
MatCard,
MatCardContent,
MatCardHeader,
@@ -19,17 +19,15 @@ import {FrameManagerService} from '../../services/frame-manager.service';
MatIcon,
MatIconButton,
MatTab,
MatTabGroup
],
MatTabGroup,
MatTooltipModule,
],
templateUrl: './frames.component.html',
styleUrl: './frames.component.scss'
})
export class FramesComponent {
constructor(
private particleManagerService: ParticleManagerService,
private frameManagerService: FrameManagerService) {
}
private particleManagerService = inject(ParticleManagerService);
private frameManagerService = inject(FrameManagerService);
/**
* Get the particle data
@@ -6,35 +6,35 @@
</app-header>
<main>
<section class="darkmodeSection">
<section class="column">
<div class="renderer-section column">
<div class="flex row">
<div class="flex side-column">
<app-particle-properties></app-particle-properties>
</div>
<div class="flex middle-column">
<app-render-container></app-render-container>
<div class="plane-controls">
<label>Plane Position (Z-axis):</label>
<mat-slider [min]="minOffset" [max]="maxOffset" step="1" #planeSlider>
<input matSliderThumb [(ngModel)]="planePosition" (input)="updatePlanePosition($event)">
</mat-slider>
<span>{{ planePosition }} offset from center</span>
<app-full-size [hideFooter]="true">
<section class="darkmodeSection full-height">
<section class="column">
<div class="renderer-section column">
<div class="flex row">
<div class="flex side-column">
<app-particle-properties></app-particle-properties>
</div>
</div>
<div class="flex side-column">
<app-particle></app-particle>
<app-frames></app-frames>
<div>
<button mat-fab extended (click)="copyJson()">
<mat-icon>content_copy</mat-icon>
Copy JSON to clipboard
</button>
<div class="flex middle-column">
<app-render-container></app-render-container>
<div class="plane-controls">
<label>Plane Position (Z-axis):</label>
<mat-slider [min]="minOffset" [max]="maxOffset" step="1" #planeSlider>
<input matSliderThumb [(ngModel)]="planePosition" (input)="updatePlanePosition($event)">
</mat-slider>
<span>{{ planePosition }} offset from center</span>
</div>
</div>
<div class="flex side-column">
<app-particle></app-particle>
<app-frames>
<button mat-icon-button matTooltip="Copy JSON to clipboard" (click)="copyJson()">
<mat-icon>content_copy</mat-icon>
</button>
</app-frames>
</div>
</div>
</div>
</div>
</section>
</section>
</section>
</app-full-size>
</main>
@@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParticlesComponent } from './particles.component';
describe('ParticlesComponent', () => {
let component: ParticlesComponent;
let fixture: ComponentFixture<ParticlesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ParticlesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ParticlesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,4 +1,4 @@
import {Component, ElementRef, ViewChild} from '@angular/core';
import {Component, ElementRef, inject, ViewChild} from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
@@ -23,6 +23,8 @@ 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';
import {MatTooltipModule} from '@angular/material/tooltip';
import {FullSizeComponent} from '@shared-components/full-size/full-size.component';
@Component({
selector: 'app-particles',
@@ -43,21 +45,20 @@ import {ParticlesService} from '@api';
PropertiesComponent,
ParticleComponent,
FramesComponent,
RenderContainerComponent
],
RenderContainerComponent,
MatTooltipModule,
FullSizeComponent
],
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,
) {
}
private readonly intersectionPlaneService = inject(IntersectionPlaneService);
private readonly particleManagerService = inject(ParticleManagerService);
private readonly matSnackBar = inject(MatSnackBar);
private readonly particlesService = inject(ParticlesService);
/**
* Update plane position based on slider