diff --git a/package.json b/package.json index fd811fb..dce925b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@angular/common": "19.2.0", "@angular/compiler": "19.2.0", "@angular/core": "19.2.0", + "@angular/cdk": "19.2.0", "@angular/forms": "19.2.0", "@angular/platform-browser": "19.2.0", "@angular/platform-browser-dynamic": "19.2.0", diff --git a/src/app/common/directives/dnd.directive.ts b/src/app/common/directives/dnd.directive.ts index c227396..4e14e6e 100644 --- a/src/app/common/directives/dnd.directive.ts +++ b/src/app/common/directives/dnd.directive.ts @@ -10,6 +10,7 @@ import { import { NewtonFile } from '../types/file.type'; + @Directive({ selector: '[dropzone]' }) @@ -17,21 +18,24 @@ export class DndDirective { @HostBinding('class.fileover') fileOver!: boolean; @Output() fileDropped = new EventEmitter(); - @HostListener('dragover', ['$event']) onDragOver(evt: any) { + @HostListener('dragover', ['$event']) + onDragOver(evt: any) { evt.preventDefault(); evt.stopPropagation(); this.fileOver = true; } - @HostListener('dragleave', ['$event']) public onDragLeave(evt: any) { + @HostListener('dragleave', ['$event']) + public onDragLeave(evt: any) { evt.preventDefault(); evt.stopPropagation(); this.fileOver = false; } - @HostListener('drop', ['$event']) public ondrop(evt: any) { + @HostListener('drop', ['$event']) + publicondrop(evt: any) { evt.preventDefault(); evt.stopPropagation(); diff --git a/src/app/common/directives/draggable.directive.ts b/src/app/common/directives/draggable.directive.ts new file mode 100644 index 0000000..9ae68af --- /dev/null +++ b/src/app/common/directives/draggable.directive.ts @@ -0,0 +1,48 @@ +import { + Directive, + Output, + EventEmitter, + HostListener +} from '@angular/core'; + + + +@Directive({ + selector: '[draggable-item]' +}) +export class DraggableDirective { + @Output() dragStart = new EventEmitter(); + @Output() dragMove = new EventEmitter(); + @Output() dragEnd = new EventEmitter(); + + private dragging = false; + selected: any; + + + @HostListener('pointerdown', ['$event']) + onPointerDown(event: PointerEvent): void { + console.log("pointerdown"); + + this.dragStart.emit(event); + } + + @HostListener('document:pointermove', ['$event']) + onPointerMove(event: PointerEvent): void { + if (!this.dragging) return; + console.log("pointermove"); + + this.dragging = true; + this.dragMove.emit(event); + } + + @HostListener('document:pointerup', ['$event']) + onPointerUp(event: PointerEvent): void { + if (!this.dragging) return; + + console.log("pointerup"); + + this.dragging = false; + this.dragEnd.emit(event); + } + +} \ No newline at end of file diff --git a/src/app/editor/tabs/tab/tab.component.css b/src/app/editor/tabs/tab/tab.component.css deleted file mode 100644 index 9162d48..0000000 --- a/src/app/editor/tabs/tab/tab.component.css +++ /dev/null @@ -1,27 +0,0 @@ -.tab, -.title, -.close-button { - color: rgba(255, 255, 255, 0.64); -} - - -.title { - margin-left: 2em; - margin-right: 2em; - font-size: 4em; -} - -.title:hover { - cursor: pointer; -} - -.close-button { - background: rgba(116, 0, 0, 0.64); - border-style: solid; - border-color: rgba(0, 0, 0, 0.64); - border-width: 1px; -} - -.close-button:hover { - background: rgba(256, 0, 0, 0.64); -} \ No newline at end of file diff --git a/src/app/editor/tabs/tab/tab.component.html b/src/app/editor/tabs/tab/tab.component.html deleted file mode 100644 index 85fa0a6..0000000 --- a/src/app/editor/tabs/tab/tab.component.html +++ /dev/null @@ -1,4 +0,0 @@ - - {{title}} - - \ No newline at end of file diff --git a/src/app/editor/tabs/tab/tab.component.ts b/src/app/editor/tabs/tab/tab.component.ts deleted file mode 100644 index 2e4af6f..0000000 --- a/src/app/editor/tabs/tab/tab.component.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Component } from '@angular/core'; - -import { EditorsService } from '../../../common/services/editor/editors.service'; - - - -@Component({ - selector: 'tab', - standalone: true, - imports: [ - ], - templateUrl: './tab.component.html', - styleUrl: './tab.component.css', - host: { - 'class': '' - } -}) -export class TabComponent { - - title: string; - path: string; - ref: any; - - - constructor( - private editorsService: EditorsService, - ) { - this.title = "[NO TITLE]"; - } - - ngOnDestroy() { - } - - setTabToEditor() { - this.editorsService.setTabToEditor(this.path); - } - - closeTab() { - this.editorsService.closeTab(this.path); - this.ref.destroy(); - } -} \ No newline at end of file diff --git a/src/app/editor/tabs/tabs.component.css b/src/app/editor/tabs/tabs.component.css index e69de29..6ff7c3e 100644 --- a/src/app/editor/tabs/tabs.component.css +++ b/src/app/editor/tabs/tabs.component.css @@ -0,0 +1,26 @@ +.tab, +.title, +.close-button { + color: rgba(255, 255, 255, 0.64); +} + +.tab:hover { + cursor: pointer; +} + +.title { + margin-left: 2em; + margin-right: 2em; + font-size: 4em; +} + +.close-button { + background: rgba(116, 0, 0, 0.64); + border-style: solid; + border-color: rgba(0, 0, 0, 0.64); + border-width: 1px; +} + +.close-button:hover { + background: rgba(256, 0, 0, 0.64); +} \ No newline at end of file diff --git a/src/app/editor/tabs/tabs.component.html b/src/app/editor/tabs/tabs.component.html index c72e44d..abbb25c 100644 --- a/src/app/editor/tabs/tabs.component.html +++ b/src/app/editor/tabs/tabs.component.html @@ -1,2 +1,21 @@ - - +
+ +
+ {{tab.title}} + +
+ +
\ No newline at end of file diff --git a/src/app/editor/tabs/tabs.component.ts b/src/app/editor/tabs/tabs.component.ts index 72c9f41..6fdd20d 100644 --- a/src/app/editor/tabs/tabs.component.ts +++ b/src/app/editor/tabs/tabs.component.ts @@ -1,7 +1,9 @@ -import { Component, ElementRef, ViewChild, TemplateRef, ComponentRef, ViewContainerRef } from '@angular/core'; +import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop'; import { Subject, takeUntil } from 'rxjs'; -import { TabComponent } from './tab/tab.component'; +import { EditorsService } from '../../common/services/editor/editors.service'; import { TabsService } from '../../common/services/editor/tabs/tabs.service'; import { ServiceMessage } from '../../common/types/service-message.type'; @@ -12,6 +14,9 @@ import { ServiceMessage } from '../../common/types/service-message.type'; selector: 'tabs', standalone: true, imports: [ + CommonModule, + CdkDropList, + CdkDrag, ], templateUrl: './tabs.component.html', styleUrl: './tabs.component.css', @@ -22,16 +27,17 @@ import { ServiceMessage } from '../../common/types/service-message.type'; export class TabsComponent { private unsubscribe = new Subject(); - @ViewChild('containerRef', {read: ViewContainerRef}) containerRef!: ViewContainerRef; - tabs: Map>; activeTab!: string; + tabs: any[] = []; + newIndex: number = -1; - constructor(private tabsService: TabsService) { - this.tabs = new Map>(); + constructor( + private editorsService: EditorsService, + private tabsService: TabsService + ) { } - public ngAfterViewInit(): void { this.tabsService.getData$().pipe( takeUntil(this.unsubscribe) @@ -41,20 +47,74 @@ export class TabsComponent { }); } - ngOnDestroy() { + ngOnDestroy(): void { this.unsubscribe.next(); this.unsubscribe.complete(); } - private createTab(title: string, uuid: string, path: string) { - const component = this.containerRef.createComponent(TabComponent); - component.instance.title = title; - component.instance.path = path; - component.instance.ref = component; - - this.tabs.set(uuid, component) - - return component; + private createTab(title: string, uuid: string, path: string): void { + this.tabs.push({title: title, path: path, uuid: uuid}) } -} \ No newline at end of file + handleAction(event: any): void { + let target = event.target; + + if ( target.classList.contains("tab") ) { + this.editorsService.setTabToEditor( + event.srcElement.getAttribute("title") + ); + } else if ( target.classList.contains("title") ) { + this.editorsService.setTabToEditor( + event.srcElement.parentElement.getAttribute("title") + ); + } else if ( target.classList.contains("close-button") ) { + this.closeTab( + event.srcElement.parentElement.getAttribute("title") + ); + } + + } + + closeTab(fpath: string): void { + this.editorsService.closeTab(fpath); + + for (let i = 0; i < this.tabs.length; i++) { + if (this.tabs[i].path == fpath) { + this.tabs.splice(i, 1); + } + } + + } + + + moved(event: any): void { + let target = event.event.target; + let fpath = ""; + + if ( target.classList.contains("title") ) { + fpath = target.parentElement.getAttribute("title") + } else if ( target.classList.contains("close-button") ) { + fpath = target.parentElement.getAttribute("title") + } else ( + fpath = target.getAttribute("title") + ) + + for (let i = 0; i < this.tabs.length; i++) { + if (this.tabs[i].path == fpath) { + this.newIndex = i; + } + } + + } + + dropped(event: CdkDragDrop): void { + if (this.newIndex == -1) return; + + moveItemInArray(this.tabs, event.previousIndex, this.newIndex); + this.newIndex = -1; + + // event.currentIndex not updating for some reason... + // moveItemInArray(this.tabs, event.previousIndex, event.currentIndex); + } + +}