Testing changing of tab order

This commit is contained in:
itdominator 2025-06-05 00:07:21 -05:00
parent dabc089b83
commit 6e5af8e85d
9 changed files with 181 additions and 96 deletions

View File

@ -21,6 +21,7 @@
"@angular/common": "19.2.0", "@angular/common": "19.2.0",
"@angular/compiler": "19.2.0", "@angular/compiler": "19.2.0",
"@angular/core": "19.2.0", "@angular/core": "19.2.0",
"@angular/cdk": "19.2.0",
"@angular/forms": "19.2.0", "@angular/forms": "19.2.0",
"@angular/platform-browser": "19.2.0", "@angular/platform-browser": "19.2.0",
"@angular/platform-browser-dynamic": "19.2.0", "@angular/platform-browser-dynamic": "19.2.0",

View File

@ -10,6 +10,7 @@ import {
import { NewtonFile } from '../types/file.type'; import { NewtonFile } from '../types/file.type';
@Directive({ @Directive({
selector: '[dropzone]' selector: '[dropzone]'
}) })
@ -17,21 +18,24 @@ export class DndDirective {
@HostBinding('class.fileover') fileOver!: boolean; @HostBinding('class.fileover') fileOver!: boolean;
@Output() fileDropped = new EventEmitter<any>(); @Output() fileDropped = new EventEmitter<any>();
@HostListener('dragover', ['$event']) onDragOver(evt: any) { @HostListener('dragover', ['$event'])
onDragOver(evt: any) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
this.fileOver = true; this.fileOver = true;
} }
@HostListener('dragleave', ['$event']) public onDragLeave(evt: any) { @HostListener('dragleave', ['$event'])
public onDragLeave(evt: any) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
this.fileOver = false; this.fileOver = false;
} }
@HostListener('drop', ['$event']) public ondrop(evt: any) { @HostListener('drop', ['$event'])
publicondrop(evt: any) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();

View File

@ -0,0 +1,48 @@
import {
Directive,
Output,
EventEmitter,
HostListener
} from '@angular/core';
@Directive({
selector: '[draggable-item]'
})
export class DraggableDirective {
@Output() dragStart = new EventEmitter<PointerEvent>();
@Output() dragMove = new EventEmitter<PointerEvent>();
@Output() dragEnd = new EventEmitter<PointerEvent>();
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);
}
}

View File

@ -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);
}

View File

@ -1,4 +0,0 @@
<span class="tab noselect" title="{{path}}">
<span class="title" (mouseup)="setTabToEditor()">{{title}}</span>
<button class="close-button" (mouseup)="closeTab()">X</button>
</span>

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -1,2 +1,21 @@
<ng-container #containerRef> <div cdkDropList
</ng-container> cdkDropListSortingDisabled
cdkDropListLockAxis="x"
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="dropped($event)"
(click)="handleAction($event)"
>
<div *ngFor="let tab of tabs"
cdkDrag
(cdkDragMoved)="moved($event)"
title="{{tab.path}}"
uuid="{{tab.uuid}}"
path="{{tab.path}}"
class="tab noselect"
>
<span class="title">{{tab.title}}</span>
<button class="close-button">X</button>
</div>
</div>

View File

@ -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 { 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 { TabsService } from '../../common/services/editor/tabs/tabs.service';
import { ServiceMessage } from '../../common/types/service-message.type'; import { ServiceMessage } from '../../common/types/service-message.type';
@ -12,6 +14,9 @@ import { ServiceMessage } from '../../common/types/service-message.type';
selector: 'tabs', selector: 'tabs',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
CdkDropList,
CdkDrag,
], ],
templateUrl: './tabs.component.html', templateUrl: './tabs.component.html',
styleUrl: './tabs.component.css', styleUrl: './tabs.component.css',
@ -22,16 +27,17 @@ import { ServiceMessage } from '../../common/types/service-message.type';
export class TabsComponent { export class TabsComponent {
private unsubscribe = new Subject<void>(); private unsubscribe = new Subject<void>();
@ViewChild('containerRef', {read: ViewContainerRef}) containerRef!: ViewContainerRef;
tabs: Map<string, ComponentRef<TabComponent>>;
activeTab!: string; activeTab!: string;
tabs: any[] = [];
newIndex: number = -1;
constructor(private tabsService: TabsService) { constructor(
this.tabs = new Map<string, ComponentRef<TabComponent>>(); private editorsService: EditorsService,
private tabsService: TabsService
) {
} }
public ngAfterViewInit(): void { public ngAfterViewInit(): void {
this.tabsService.getData$().pipe( this.tabsService.getData$().pipe(
takeUntil(this.unsubscribe) takeUntil(this.unsubscribe)
@ -41,20 +47,74 @@ export class TabsComponent {
}); });
} }
ngOnDestroy() { ngOnDestroy(): void {
this.unsubscribe.next(); this.unsubscribe.next();
this.unsubscribe.complete(); this.unsubscribe.complete();
} }
private createTab(title: string, uuid: string, path: string) { private createTab(title: string, uuid: string, path: string): void {
const component = this.containerRef.createComponent(TabComponent); this.tabs.push({title: title, path: path, uuid: uuid})
component.instance.title = title; }
component.instance.path = path;
component.instance.ref = component;
this.tabs.set(uuid, component) handleAction(event: any): void {
let target = event.target;
return component; 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<any>): 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);
} }
} }