import { Component, ChangeDetectorRef, DestroyRef, ElementRef, ViewChild, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { TabsService } from '../../common/services/editor/tabs/tabs.service'; import { ServiceMessage } from '../../common/types/service-message.type'; import { ButtonMap } from '../../common/constants/button.map'; @Component({ selector: 'tabs', standalone: true, imports: [ CommonModule, CdkDropList, CdkDrag, ], templateUrl: './tabs.component.html', styleUrl: './tabs.component.css', host: { 'class': 'tabs scroller' } }) export class TabsComponent { readonly #destroyRef = inject(DestroyRef); private tabsService: TabsService = inject(TabsService); private changeDetectorRef: ChangeDetectorRef = inject(ChangeDetectorRef); @ViewChild('contextMenu') contextMenu!: ElementRef; public showContextMenu: boolean = false; tabs: any[] = this.tabsService.tabs; targetEvent!: any; constructor() { this.loadSubscribers(); } private loadSubscribers() { this.tabsService.getMessage$().pipe( takeUntilDestroyed(this.#destroyRef) ).subscribe((message: ServiceMessage) => { let elm = document.querySelectorAll(`[title="${message.filePath}"]`)[1]; switch ( message.action ) { case "create-tab": this.createTab(message.fileName, message.fileUUID, message.filePath); break; case "file-changed": elm.classList.add("file-changed"); elm.classList.remove("file-deleted"); break; case "file-deleted": elm.classList.add("file-deleted"); elm.classList.remove("file-changed"); break; case "file-saved": elm.classList.remove("file-deleted"); elm.classList.remove("file-changed"); break; default: break; } }); } protected handleAction(event: any): void { let target = event.target; if (ButtonMap.RIGHT === event.button) { let menuElm = this.contextMenu.nativeElement; let pageX = event.clientX; let pageY = event.clientY; const origin = { left: pageX + 5, top: pageY - 5 }; menuElm.style.left = `${origin.left}px`; menuElm.style.top = `${origin.top}px`; this.showContextMenu = true; this.targetEvent = event; return; } this.showContextMenu = false; this.processTargetEvent(event); } public hideContextMenu() { this.showContextMenu = false; } public contextMenuClicked(event: any) { this.showContextMenu = false; const command = event.target.getAttribute("command"); const args = event.target.getAttribute("args"); if (!command) return; this[command]( (args) ? args : null ); } public createTab(title: string, uuid: string, path: string): void { this.tabsService.push({title: title, uuid: uuid, path: path}); this.changeDetectorRef.detectChanges(); } private moved(event: any): void { let target = event.event.target; let fpath = ""; if ( target.classList.contains("title") || target.classList.contains("close-button") ) { fpath = target.parentElement.getAttribute("title") } else ( fpath = target.getAttribute("title") ) this.tabsService.setNewTargetIndex(fpath); } protected dropped(event: CdkDragDrop): void { this.tabsService.move(event.previousIndex); } private close(event: any): void { this.tabsService.closeTab( this.targetEvent.srcElement.parentElement.getAttribute("title") ); } private closeAll(event: any): void { let elm = this.targetEvent.srcElement.parentElement; let startElm = elm; // clear right while (elm) { elm = elm.nextSibling; if (!elm || elm.nodeType == 8) continue; this.tabsService.closeTab( elm.getAttribute("title") ); } // clear left elm = startElm; while (elm) { elm = elm.previousSibling; if (!elm || elm.nodeType == 8) continue; this.tabsService.closeTab( elm.getAttribute("title") ); } // clear initial target elm = startElm; this.tabsService.closeTab( elm.getAttribute("title") ); } private closeAllLeft(event: any): void { let elm = this.targetEvent.srcElement.parentElement; // clear left while (elm) { elm = elm.previousSibling; if (!elm || elm.nodeType == 8) continue; this.tabsService.closeTab( elm.getAttribute("title") ); } } private closeAllRight(event: any): void { let elm = this.targetEvent.srcElement.parentElement; // clear right while (elm) { elm = elm.nextSibling; if (!elm || elm.nodeType == 8) continue; this.tabsService.closeTab( elm.getAttribute("title") ); } } private processTargetEvent(event: any): void { let target = event.target; if ( target.classList.contains("tab") ) { this.tabsService.sendEditorsServiceAMessage( "set-tab-to-editor", event.srcElement.getAttribute("title") ); } else if ( target.classList.contains("title") ) { this.tabsService.sendEditorsServiceAMessage( "set-tab-to-editor", event.srcElement.parentElement.getAttribute("title") ); } else if ( target.classList.contains("close-button") ) { this.tabsService.closeTab( event.srcElement.parentElement.getAttribute("title") ); } } }