diff --git a/cypress/e2e/drag-to-connect.component.cy.ts b/cypress/e2e/drag-to-connect.component.cy.ts index 3718d23..6ab2b55 100644 --- a/cypress/e2e/drag-to-connect.component.cy.ts +++ b/cypress/e2e/drag-to-connect.component.cy.ts @@ -4,6 +4,7 @@ describe('DragToConnectComponent', () => { }) it('should start creating a connection and show connection-for-create element', function () { + cy.get('f-flow').scrollIntoView(); cy.get('.f-connection-for-create').should('exist') .invoke('css', 'display').should('equal', 'none'); diff --git a/cypress/e2e/drag-to-reassign.component.cy.ts b/cypress/e2e/drag-to-reassign.component.cy.ts index 9aa8f8c..01132c5 100644 --- a/cypress/e2e/drag-to-reassign.component.cy.ts +++ b/cypress/e2e/drag-to-reassign.component.cy.ts @@ -3,19 +3,27 @@ describe('DragToReassignComponent', () => { cy.visit('http://localhost:4200/examples/drag-to-reassign') }) - it('should drag from input to anoyher input and reassign the connection', function() { - cy.get('#connection_f-connection-012').should('exist'); - - cy.get('.f-connection-drag-handle') - .trigger('mousedown', { button: 0, force: true }) - .trigger('mousemove', { clientX: 0, clientY: 0 }) - .trigger('mousemove', { clientX: 20, clientY: 10 }) - .get('div[data-f-input-id=\'f-node-input-1\']') - .trigger('mousemove', { clientX: 20, clientY: 10 }) - .trigger('mouseup'); - - cy.get('#connection_f-connection-012').should('not.exist'); - cy.get('#connection_for_selection_f-connection-11f-node-input-1').should('exist'); + it('should drag from input to anoyher input and reassign the connection', function () { + cy.get('f-flow').scrollIntoView(); + + cy.get('#connection_f-connection-01input-1').should('exist'); + cy.get('div[data-f-input-id=\'input-1\']').should('exist'); + cy.get('div[data-f-input-id=\'input-2\']').should('exist'); + + cy.get('div[data-f-input-id="input-2"]').then(($target) => { + const targetRect = $target[ 0 ].getBoundingClientRect(); + const endY = targetRect.y + targetRect.height / 2; + + cy.get('.f-connection-drag-handle') + .trigger('mousedown', { button: 0, force: true }) + .trigger('mousemove', { clientY: 0, force: true }) + .get('div[data-f-input-id=\'input-2\']') + .trigger('mousemove', { clientY: endY, force: true }) + .trigger('mouseup', { force: true }); + + cy.get('#connection_f-connection-01input-1').should('not.exist'); + cy.get('#connection_for_selection_f-connection-11input-2').should('exist'); + }); }); }) diff --git a/cypress/e2e/remove-connection-on-drop.component.cy.ts b/cypress/e2e/remove-connection-on-drop.component.cy.ts index f266e54..d7e95d5 100644 --- a/cypress/e2e/remove-connection-on-drop.component.cy.ts +++ b/cypress/e2e/remove-connection-on-drop.component.cy.ts @@ -4,14 +4,17 @@ describe('RemoveConnectionOnDropComponent', () => { }) it('should drag connection from input to any place and remove the connection', function () { + cy.get('f-flow').scrollIntoView(); cy.get('#connection_f-connection-012').should('exist'); cy.get('.f-connection').should('have.length', 2); - cy.get('.f-connection-drag-handle').first() + cy.get('.f-connection-drag-handle') + .first() .trigger('mousedown', { button: 0, force: true }) - .trigger('mousemove', { clientX: 0, clientY: 0 }) - .trigger('mousemove', { clientX: 420, clientY: 110 }) - .trigger('mouseup'); + .trigger('mousemove', { clientY: 0, force: true }) + .trigger('mousemove', { clientY: 200, clientX: 0, force: true }) + .trigger('mouseup', { force: true }); + cy.get('#connection_f-connection-012').should('not.exist'); cy.get('.f-connection').should('have.length', 1); diff --git a/cypress/screenshots/remove-connection-on-drop.component.cy.ts/RemoveConnectionOnDropComponent -- should drag connection from input to any place and remove the connection (failed).png b/cypress/screenshots/remove-connection-on-drop.component.cy.ts/RemoveConnectionOnDropComponent -- should drag connection from input to any place and remove the connection (failed).png deleted file mode 100644 index ecc752c..0000000 Binary files a/cypress/screenshots/remove-connection-on-drop.component.cy.ts/RemoveConnectionOnDropComponent -- should drag connection from input to any place and remove the connection (failed).png and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 0bd4cfa..105083b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@angular/router": "^18.2.0", "@angular/ssr": "^18.2.3", "@cypress/angular": "^2.1.0", - "@foblex/2d": "1.1.0", + "@foblex/2d": "1.1.4", "@foblex/drag-toolkit": "1.1.0", "@foblex/f-docs": "1.4.9", "@foblex/mediator": "1.1.0", @@ -2846,9 +2846,9 @@ } }, "node_modules/@foblex/2d": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@foblex/2d/-/2d-1.1.0.tgz", - "integrity": "sha512-Fd6jIL9dM6NuqDx5Zn4lLGH2wEtdKoLsR/8iURqw8wIheUcyoQsHAZk07InLxP4yHnGuuspmf7jPelemafMLEw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@foblex/2d/-/2d-1.1.4.tgz", + "integrity": "sha512-GRuxnVwZj/g9oZSBvEtAVb7HduFsI54AajtM3HnJw58NPRTRPJYOJ0fO2JmHNklQuqoQhqCeOUrt8RFyRz1yRQ==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/package.json b/package.json index d5323ec..29e5b61 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@angular/router": "^18.2.0", "@angular/ssr": "^18.2.3", "@cypress/angular": "^2.1.0", - "@foblex/2d": "1.1.0", + "@foblex/2d": "1.1.4", "@foblex/drag-toolkit": "1.1.0", "@foblex/f-docs": "1.4.9", "@foblex/mediator": "1.1.0", diff --git a/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.html b/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.html index eb5a651..613cf51 100644 --- a/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.html +++ b/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.html @@ -8,8 +8,8 @@ }
Output
-
Input
-
Input
+
Input
+
Input
diff --git a/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.ts b/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.ts index ec4294d..d6347a7 100644 --- a/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.ts +++ b/projects/f-examples/connections/drag-to-reassign/drag-to-reassign.component.ts @@ -1,4 +1,9 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, ElementRef, inject, + ViewChild +} from '@angular/core'; import { FCanvasComponent, FFlowModule, FReassignConnectionEvent } from '@foblex/flow'; @Component({ @@ -13,24 +18,22 @@ import { FCanvasComponent, FFlowModule, FReassignConnectionEvent } from '@foblex }) export class DragToReassignComponent { + private _elementReference = inject(ElementRef); + private _changeDetectorRef = inject(ChangeDetectorRef); + @ViewChild(FCanvasComponent, { static: true }) public fCanvas!: FCanvasComponent; public connections: { outputId: string, inputId: string }[] = [ - { outputId: '1', inputId: '2' }, + { outputId: '1', inputId: 'input-1' }, ]; - constructor( - private changeDetectorRef: ChangeDetectorRef - ) { - } - public reassignConnection(event: FReassignConnectionEvent): void { - if(!event.newFInputId) { + if (!event.newFInputId) { return; } this.connections = [ { outputId: event.fOutputId, inputId: event.newFInputId } ]; - this.changeDetectorRef.detectChanges(); + this._changeDetectorRef.detectChanges(); } public onLoaded(): void { diff --git a/projects/f-examples/connections/remove-connection-on-drop/remove-connection-on-drop.component.ts b/projects/f-examples/connections/remove-connection-on-drop/remove-connection-on-drop.component.ts index de502ca..25fed51 100644 --- a/projects/f-examples/connections/remove-connection-on-drop/remove-connection-on-drop.component.ts +++ b/projects/f-examples/connections/remove-connection-on-drop/remove-connection-on-drop.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, inject, ViewChild } from '@angular/core'; import { FCanvasComponent, FFlowComponent, @@ -19,6 +19,9 @@ import { IPoint } from '@foblex/2d'; }) export class RemoveConnectionOnDropComponent { + private _elementReference = inject(ElementRef); + private _changeDetectorRef = inject(ChangeDetectorRef); + @ViewChild(FCanvasComponent, { static: true }) public fCanvas!: FCanvasComponent; @@ -41,18 +44,13 @@ export class RemoveConnectionOnDropComponent { { outputId: this.nodes[1].id, inputId: this.nodes[2].id } ]; - constructor( - private changeDetectorRef: ChangeDetectorRef - ) { - } - public onConnectionDropped(event: FReassignConnectionEvent): void { if (!event.newFInputId) { this.removeConnection(event); } else { this.reassignConnection(event); } - this.changeDetectorRef.detectChanges(); + this._changeDetectorRef.detectChanges(); } private removeConnection(event: FReassignConnectionEvent): void { diff --git a/projects/f-flow/package.json b/projects/f-flow/package.json index 98a1f99..389bbe1 100644 --- a/projects/f-flow/package.json +++ b/projects/f-flow/package.json @@ -33,7 +33,7 @@ "@angular/core": ">=15.0.0", "@foblex/platform": "1.0.4", "@foblex/mediator": "1.1.0", - "@foblex/2d": "1.1.0", + "@foblex/2d": "1.1.4", "@foblex/drag-toolkit": "1.1.0", "@foblex/utils": "1.1.0" }, diff --git a/projects/f-flow/src/domain/f-canvas/fit-to-flow/fit-to-flow.execution.ts b/projects/f-flow/src/domain/f-canvas/fit-to-flow/fit-to-flow.execution.ts index a1543bb..9065023 100644 --- a/projects/f-flow/src/domain/f-canvas/fit-to-flow/fit-to-flow.execution.ts +++ b/projects/f-flow/src/domain/f-canvas/fit-to-flow/fit-to-flow.execution.ts @@ -3,7 +3,7 @@ import { FitToFlowRequest } from './fit-to-flow-request'; import { FExecutionRegister, FMediator, IExecution } from '@foblex/mediator'; import { IPoint, IRect, ITransformModel, PointExtensions, RectExtensions } from '@foblex/2d'; import { FComponentsStore } from '../../../f-storage'; -import { GetNodesRectRequest, RedrawCanvasWithAnimationRequest } from '../../../domain'; +import { CalculateNodesBoundingBoxRequest, RedrawCanvasWithAnimationRequest } from '../../../domain'; @Injectable() @FExecutionRegister(FitToFlowRequest) @@ -18,7 +18,7 @@ export class FitToFlowExecution implements IExecution { private _fMediator = inject(FMediator); public handle(request: FitToFlowRequest): void { - const fNodesRect = this._fMediator.send(new GetNodesRectRequest()) || RectExtensions.initialize(); + const fNodesRect = this._fMediator.send(new CalculateNodesBoundingBoxRequest()) || RectExtensions.initialize(); if (fNodesRect.width === 0 || fNodesRect.height === 0) { return; } diff --git a/projects/f-flow/src/domain/f-canvas/reset-scale-and-center/reset-scale-and-center.execution.ts b/projects/f-flow/src/domain/f-canvas/reset-scale-and-center/reset-scale-and-center.execution.ts index cd5c64a..40b1d02 100644 --- a/projects/f-flow/src/domain/f-canvas/reset-scale-and-center/reset-scale-and-center.execution.ts +++ b/projects/f-flow/src/domain/f-canvas/reset-scale-and-center/reset-scale-and-center.execution.ts @@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core'; import { ResetScaleAndCenterRequest } from './reset-scale-and-center-request'; import { FExecutionRegister, FMediator, IExecution } from '@foblex/mediator'; import { IPoint, IRect, ITransformModel, PointExtensions, RectExtensions } from '@foblex/2d'; -import { GetNodesRectRequest, RedrawCanvasWithAnimationRequest } from '../../../domain'; +import { CalculateNodesBoundingBoxRequest, RedrawCanvasWithAnimationRequest } from '../../../domain'; import { FComponentsStore } from '../../../f-storage'; @Injectable() @@ -18,7 +18,7 @@ export class ResetScaleAndCenterExecution implements IExecution(new GetNodesRectRequest()) || RectExtensions.initialize(); + const fNodesRect = this._fMediator.send(new CalculateNodesBoundingBoxRequest()) || RectExtensions.initialize(); if (fNodesRect.width === 0 || fNodesRect.height === 0) { return; } diff --git a/projects/f-flow/src/domain/f-flow/get-flow/get-flow-request.ts b/projects/f-flow/src/domain/f-flow/get-flow/get-flow-request.ts new file mode 100644 index 0000000..6194779 --- /dev/null +++ b/projects/f-flow/src/domain/f-flow/get-flow/get-flow-request.ts @@ -0,0 +1,3 @@ +export class GetFlowRequest { + +} diff --git a/projects/f-flow/src/domain/f-flow/get-flow/get-flow.execution.ts b/projects/f-flow/src/domain/f-flow/get-flow/get-flow.execution.ts new file mode 100644 index 0000000..27376c1 --- /dev/null +++ b/projects/f-flow/src/domain/f-flow/get-flow/get-flow.execution.ts @@ -0,0 +1,20 @@ +import { inject, Injectable } from '@angular/core'; +import { FExecutionRegister, IExecution } from '@foblex/mediator'; +import { GetFlowRequest } from './get-flow-request'; +import { FComponentsStore } from '../../../f-storage'; +import { FFlowBase } from '../../../f-flow'; + +@Injectable() +@FExecutionRegister(GetFlowRequest) +export class GetFlowExecution implements IExecution { + + private _fComponentsStore = inject(FComponentsStore); + + public handle(request: GetFlowRequest): FFlowBase { + const result = this._fComponentsStore.fFlow; + if (!result) { + throw new Error(`Flow not found in store`); + } + return result; + } +} diff --git a/projects/f-flow/src/domain/f-flow/get-flow/index.ts b/projects/f-flow/src/domain/f-flow/get-flow/index.ts new file mode 100644 index 0000000..8cde4ff --- /dev/null +++ b/projects/f-flow/src/domain/f-flow/get-flow/index.ts @@ -0,0 +1,3 @@ +export * from './get-flow.execution'; + +export * from './get-flow-request'; diff --git a/projects/f-flow/src/domain/f-flow/index.ts b/projects/f-flow/src/domain/f-flow/index.ts index 405bed7..02870ff 100644 --- a/projects/f-flow/src/domain/f-flow/index.ts +++ b/projects/f-flow/src/domain/f-flow/index.ts @@ -1,5 +1,7 @@ export * from './add-flow-to-store'; +export * from './get-flow'; + export * from './get-flow-host-element'; export * from './remove-flow-from-store'; diff --git a/projects/f-flow/src/domain/f-flow/providers.ts b/projects/f-flow/src/domain/f-flow/providers.ts index 4e746fd..3550a17 100644 --- a/projects/f-flow/src/domain/f-flow/providers.ts +++ b/projects/f-flow/src/domain/f-flow/providers.ts @@ -1,11 +1,14 @@ import { GetFlowHostElementExecution } from './get-flow-host-element'; import { AddFlowToStoreExecution } from './add-flow-to-store'; import { RemoveFlowFromStoreExecution } from './remove-flow-from-store'; +import { GetFlowExecution } from './get-flow'; export const F_FLOW_FEATURES = [ AddFlowToStoreExecution, + GetFlowExecution, + GetFlowHostElementExecution, RemoveFlowFromStoreExecution diff --git a/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.execution.ts b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.execution.ts new file mode 100644 index 0000000..db2a58f --- /dev/null +++ b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.execution.ts @@ -0,0 +1,24 @@ +import { IRect, RectExtensions } from '@foblex/2d'; +import { CalculateNodesBoundingBoxRequest } from './calculate-nodes-bounding-box.request'; +import { inject, Injectable } from '@angular/core'; +import { FComponentsStore } from '../../../f-storage'; +import { FExecutionRegister, IExecution } from '@foblex/mediator'; + +@Injectable() +@FExecutionRegister(CalculateNodesBoundingBoxRequest) +export class CalculateNodesBoundingBoxExecution implements IExecution { + + private _fComponentsStore = inject(FComponentsStore); + + public handle(request: CalculateNodesBoundingBoxRequest): IRect | null { + return RectExtensions.union(this._getNodesRects()); + } + + private _getNodesRects(): IRect[] { + return this._fComponentsStore.fNodes.map((x) => this._getElementRect(x.hostElement)); + } + + private _getElementRect(element: HTMLElement): IRect { + return RectExtensions.fromElement(element); + } +} diff --git a/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.request.ts b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.request.ts new file mode 100644 index 0000000..52a739f --- /dev/null +++ b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/calculate-nodes-bounding-box.request.ts @@ -0,0 +1,3 @@ +export class CalculateNodesBoundingBoxRequest { + +} diff --git a/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/index.ts b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/index.ts new file mode 100644 index 0000000..c9d1306 --- /dev/null +++ b/projects/f-flow/src/domain/f-node/calculate-nodes-bounding-box/index.ts @@ -0,0 +1,3 @@ +export * from './calculate-nodes-bounding-box.execution'; + +export * from './calculate-nodes-bounding-box.request'; diff --git a/projects/f-flow/src/domain/f-node/get-nodes/get-nodes-request.ts b/projects/f-flow/src/domain/f-node/get-nodes/get-nodes-request.ts new file mode 100644 index 0000000..2607646 --- /dev/null +++ b/projects/f-flow/src/domain/f-node/get-nodes/get-nodes-request.ts @@ -0,0 +1,3 @@ +export class GetNodesRequest { + +} diff --git a/projects/f-flow/src/domain/f-node/get-nodes/get-nodes.execution.ts b/projects/f-flow/src/domain/f-node/get-nodes/get-nodes.execution.ts new file mode 100644 index 0000000..dc2b858 --- /dev/null +++ b/projects/f-flow/src/domain/f-node/get-nodes/get-nodes.execution.ts @@ -0,0 +1,16 @@ +import { inject, Injectable } from '@angular/core'; +import { FExecutionRegister, IExecution } from '@foblex/mediator'; +import { GetNodesRequest } from './get-nodes-request'; +import { FComponentsStore } from '../../../f-storage'; +import { FNodeBase } from '../../../f-node'; + +@Injectable() +@FExecutionRegister(GetNodesRequest) +export class GetNodesExecution implements IExecution { + + private _fComponentsStore = inject(FComponentsStore); + + public handle(request: GetNodesRequest): FNodeBase[] { + return this._fComponentsStore.fNodes; + } +} diff --git a/projects/f-flow/src/domain/f-node/get-nodes/index.ts b/projects/f-flow/src/domain/f-node/get-nodes/index.ts new file mode 100644 index 0000000..ad51769 --- /dev/null +++ b/projects/f-flow/src/domain/f-node/get-nodes/index.ts @@ -0,0 +1,3 @@ +export * from './get-nodes.execution'; + +export * from './get-nodes-request'; diff --git a/projects/f-flow/src/domain/f-node/index.ts b/projects/f-flow/src/domain/f-node/index.ts index 2b76a4e..ca4cc6c 100644 --- a/projects/f-flow/src/domain/f-node/index.ts +++ b/projects/f-flow/src/domain/f-node/index.ts @@ -1,5 +1,9 @@ export * from './add-node-to-store'; +export * from './calculate-nodes-bounding-box'; + +export * from './get-nodes'; + export * from './update-node-when-state-or-size-changed'; export * from './remove-node-from-store'; diff --git a/projects/f-flow/src/domain/f-node/providers.ts b/projects/f-flow/src/domain/f-node/providers.ts index a38eb5d..3ab8602 100644 --- a/projects/f-flow/src/domain/f-node/providers.ts +++ b/projects/f-flow/src/domain/f-node/providers.ts @@ -1,11 +1,17 @@ import { AddNodeToStoreExecution } from './add-node-to-store'; import { RemoveNodeFromStoreExecution } from './remove-node-from-store'; import { UpdateNodeWhenStateOrSizeChangedExecution } from './update-node-when-state-or-size-changed'; +import { GetNodesExecution } from './get-nodes'; +import { CalculateNodesBoundingBoxExecution } from './calculate-nodes-bounding-box'; export const F_NODE_FEATURES = [ AddNodeToStoreExecution, + CalculateNodesBoundingBoxExecution, + + GetNodesExecution, + UpdateNodeWhenStateOrSizeChangedExecution, RemoveNodeFromStoreExecution diff --git a/projects/f-flow/src/domain/f-node/update-node-when-state-or-size-changed/update-node-when-state-or-size-changed.execution.ts b/projects/f-flow/src/domain/f-node/update-node-when-state-or-size-changed/update-node-when-state-or-size-changed.execution.ts index 3db0d2f..b152656 100644 --- a/projects/f-flow/src/domain/f-node/update-node-when-state-or-size-changed/update-node-when-state-or-size-changed.execution.ts +++ b/projects/f-flow/src/domain/f-node/update-node-when-state-or-size-changed/update-node-when-state-or-size-changed.execution.ts @@ -12,7 +12,8 @@ import { FResizeChannel } from '../../../reactivity'; @Injectable() @FExecutionRegister(UpdateNodeWhenStateOrSizeChangedRequest) -export class UpdateNodeWhenStateOrSizeChangedExecution implements IExecution { +export class UpdateNodeWhenStateOrSizeChangedExecution + implements IExecution { private _fMediator = inject(FMediator); diff --git a/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.execution.ts b/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.execution.ts deleted file mode 100644 index a9a069d..0000000 --- a/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.execution.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { IRect, RectExtensions } from '@foblex/2d'; -import { GetNodesRectRequest } from './get-nodes-rect.request'; -import { Injectable } from '@angular/core'; -import { FComponentsStore } from '../../f-storage'; -import { FExecutionRegister, IExecution } from '@foblex/mediator'; -import { FNodeBase } from '../../f-node'; - -@Injectable() -@FExecutionRegister(GetNodesRectRequest) -export class GetNodesRectExecution implements IExecution { - - constructor( - private fComponentsStore: FComponentsStore, - ) { - } - - public handle(request: GetNodesRectRequest): IRect | null { - return RectExtensions.union(this.getNodesRects()); - } - - private getNodesRects(): IRect[] { - return this.getNodes().map((x) => RectExtensions.fromElement(x.hostElement)); - } - - private getNodes(): FNodeBase[] { - return this.fComponentsStore.fNodes; - } -} diff --git a/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.request.ts b/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.request.ts deleted file mode 100644 index 7883e63..0000000 --- a/projects/f-flow/src/domain/get-nodes-rect/get-nodes-rect.request.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class GetNodesRectRequest { - -} diff --git a/projects/f-flow/src/domain/get-nodes-rect/index.ts b/projects/f-flow/src/domain/get-nodes-rect/index.ts deleted file mode 100644 index 3871659..0000000 --- a/projects/f-flow/src/domain/get-nodes-rect/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './get-nodes-rect.execution'; - -export * from './get-nodes-rect.request'; diff --git a/projects/f-flow/src/domain/index.ts b/projects/f-flow/src/domain/index.ts index 9eb0978..d43c793 100644 --- a/projects/f-flow/src/domain/index.ts +++ b/projects/f-flow/src/domain/index.ts @@ -30,14 +30,10 @@ export * from './get-flow-state'; export * from './get-scaled-node-rects-with-flow-position'; -export * from './get-nodes-rect'; - export * from './get-position-in-flow'; export * from './is-connection-under-node'; -export * from './f-connection/redraw-connections'; - export * from './sort-item-layers'; export * from './update-item-and-children-layers'; diff --git a/projects/f-flow/src/domain/providers.ts b/projects/f-flow/src/domain/providers.ts index a40a757..65dcdc8 100644 --- a/projects/f-flow/src/domain/providers.ts +++ b/projects/f-flow/src/domain/providers.ts @@ -1,5 +1,4 @@ import { GetConnectionLineExecution } from './get-connection-line'; -import { GetNodesRectExecution } from './get-nodes-rect'; import { GetElementRectInFlowExecution } from './get-element-rect-in-flow'; import { MoveFrontElementsBeforeTargetElementExecution, @@ -57,8 +56,6 @@ export const COMMON_PROVIDERS = [ GetScaledNodeRectsWithFlowPositionExecution, - GetNodesRectExecution, - GetPositionInFlowExecution, IsConnectionUnderNodeExecution, diff --git a/projects/f-flow/src/f-flow/f-flow.component.ts b/projects/f-flow/src/f-flow/f-flow.component.ts index 515bdf2..8134d09 100644 --- a/projects/f-flow/src/f-flow/f-flow.component.ts +++ b/projects/f-flow/src/f-flow/f-flow.component.ts @@ -106,13 +106,17 @@ export class FFlowComponent extends FFlowBase implements OnInit, AfterContentIni ).listen(this._destroyRef,() => { this._fMediator.send(new RedrawConnectionsRequest()); - if (!this._isLoaded) { - this._isLoaded = true; - this.fLoaded.emit(); - } + this._emitLoaded(); }); } + private _emitLoaded(): void { + if (!this._isLoaded) { + this._isLoaded = true; + this.fLoaded.emit(); + } + } + public redraw(): void { this._fMediator.send(new NotifyDataChangedRequest()); } diff --git a/projects/f-flow/src/f-minimap/domain/check-rect-is-finite.ts b/projects/f-flow/src/f-minimap/domain/check-rect-is-finite.ts deleted file mode 100644 index 64e75c3..0000000 --- a/projects/f-flow/src/f-minimap/domain/check-rect-is-finite.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IRect, RectExtensions } from '@foblex/2d'; - -export function checkRectIsFinite(rect: IRect): IRect { - if (!Number.isFinite(rect.width) || !Number.isFinite(rect.height) || !Number.isFinite(rect.x) || !Number.isFinite(rect.y)) { - return RectExtensions.initialize(0, 0, 0, 0); - } - return rect; -} diff --git a/projects/f-flow/src/f-minimap/domain/index.ts b/projects/f-flow/src/f-minimap/domain/index.ts index 8c70a6b..6e4e47b 100644 --- a/projects/f-flow/src/f-minimap/domain/index.ts +++ b/projects/f-flow/src/f-minimap/domain/index.ts @@ -4,7 +4,11 @@ export * from './minimap-drag-finalize'; export * from './minimap-drag-preparation'; -export * from './check-rect-is-finite'; +export * from './minimap-draw-nodes'; + +export * from './minimap-calculate-svg-scale-and-view-box'; + +export * from './minimap-calculate-view-box'; export * from './f-minimap.drag-handler'; diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/i-f-minimap-scale-and-view-box.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/i-f-minimap-scale-and-view-box.ts new file mode 100644 index 0000000..caed834 --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/i-f-minimap-scale-and-view-box.ts @@ -0,0 +1,8 @@ +import { IRect } from '@foblex/2d'; + +export interface IFMinimapScaleAndViewBox { + + scale: number; + + viewBox: IRect; +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/index.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/index.ts new file mode 100644 index 0000000..647140f --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/index.ts @@ -0,0 +1,6 @@ +export * from './i-f-minimap-scale-and-view-box'; + +export * from './minimap-calculate-svg-scale-and-view-box.execution'; + +export * from './minimap-calculate-svg-scale-and-view-box.request'; + diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.execution.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.execution.ts new file mode 100644 index 0000000..829c41d --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.execution.ts @@ -0,0 +1,80 @@ +import { inject, Injectable } from '@angular/core'; +import { MinimapCalculateSvgScaleAndViewBoxRequest } from './minimap-calculate-svg-scale-and-view-box.request'; +import { FExecutionRegister, FMediator, IExecution } from '@foblex/mediator'; +import { adjustRectToMinSize, IRect, ISize, RectExtensions, SizeExtensions } from '@foblex/2d'; +import { FComponentsStore } from '../../../f-storage'; +import { FCanvasBase } from '../../../f-canvas'; +import { FFlowBase } from '../../../f-flow'; +import { CalculateNodesBoundingBoxRequest } from '../../../domain'; +import { IFMinimapScaleAndViewBox } from './i-f-minimap-scale-and-view-box'; + +@Injectable() +@FExecutionRegister(MinimapCalculateSvgScaleAndViewBoxRequest) +export class MinimapCalculateSvgScaleAndViewBoxExecution + implements IExecution { + + private _fMediator = inject(FMediator); + + private _fComponentStore = inject(FComponentsStore); + + private get _fFlow(): FFlowBase { + return this._fComponentStore.fFlow!; + } + + private get _fCanvas(): FCanvasBase { + return this._fComponentStore.fCanvas!; + } + + public handle(request: MinimapCalculateSvgScaleAndViewBoxRequest): IFMinimapScaleAndViewBox { + const nodesRect = this._getScaledNodesBoundingBox(request.minSize); + const minimapRect = this._getMinimapRect(request.element); + const scale = this._calculateViewScale(nodesRect, minimapRect); + + return { + scale, + viewBox: this._calculateViewBox(nodesRect, minimapRect, scale) + } + } + + private _getScaledNodesBoundingBox(minSize: number): IRect { + const globalRect = this._calculateNodesBoundingBox(); + const flowRect = this._convertFromGlobalToFlowRect(globalRect); + const scaledRect = this._convertRectToMinimapScale(flowRect); + return adjustRectToMinSize(scaledRect, minSize); + } + + private _calculateNodesBoundingBox(): IRect { + return this._fMediator.send(new CalculateNodesBoundingBoxRequest()) + || RectExtensions.initialize(0, 0, 0, 0); + } + + private _convertFromGlobalToFlowRect(rect: IRect): IRect { + return RectExtensions.elementTransform(rect, this._fFlow!.hostElement) + } + + private _convertRectToMinimapScale(rect: IRect): IRect { + return RectExtensions.div(rect, this._fCanvas.transform.scale); + } + + private _getMinimapRect(element: SVGSVGElement): IRect { + return RectExtensions.elementTransform(RectExtensions.fromElement(element), this._fFlow.hostElement); + } + + private _calculateViewScale(nodesRect: IRect, minimapRect: IRect): number { + return Math.max(nodesRect.width / minimapRect.width, nodesRect.height / minimapRect.height); + } + + private _calculateViewBox(nodesRect: IRect, minimapRect: IRect, scale: number): IRect { + return this._calculateCenteredViewBox(nodesRect, this._calculateViewSize(minimapRect, scale)); + } + + private _calculateViewSize(minimapRect: IRect, scale: number): ISize { + return SizeExtensions.initialize(minimapRect.width * scale || 0, minimapRect.height * scale || 0); + } + + private _calculateCenteredViewBox(nodesRect: IRect, viewSize: ISize): IRect { + const centeredX = nodesRect.x - (viewSize.width - nodesRect.width) / 2; + const centeredY = nodesRect.y - (viewSize.height - nodesRect.height) / 2; + return RectExtensions.initialize(centeredX, centeredY, viewSize.width, viewSize.height); + } +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.request.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.request.ts new file mode 100644 index 0000000..a2a7499 --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-svg-scale-and-view-box/minimap-calculate-svg-scale-and-view-box.request.ts @@ -0,0 +1,8 @@ +export class MinimapCalculateSvgScaleAndViewBoxRequest { + + constructor( + public element: SVGSVGElement, + public minSize: number, + ) { + } +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/index.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/index.ts new file mode 100644 index 0000000..506e46f --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/index.ts @@ -0,0 +1,4 @@ +export * from './minimap-calculate-view-box.execution'; + +export * from './minimap-calculate-view-box.request'; + diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.execution.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.execution.ts new file mode 100644 index 0000000..79e718b --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.execution.ts @@ -0,0 +1,37 @@ +import { inject, Injectable } from '@angular/core'; +import { MinimapCalculateViewBoxRequest } from './minimap-calculate-view-box.request'; +import { FExecutionRegister, IExecution } from '@foblex/mediator'; +import { IRect, RectExtensions } from '@foblex/2d'; +import { FComponentsStore } from '../../../f-storage'; +import { FCanvasBase } from '../../../f-canvas'; +import { FFlowBase } from '../../../f-flow'; + +@Injectable() +@FExecutionRegister(MinimapCalculateViewBoxRequest) +export class MinimapCalculateViewBoxExecution implements IExecution { + + private _fComponentStore = inject(FComponentsStore); + + private get _fFlow(): FFlowBase | undefined { + return this._fComponentStore.fFlow; + } + + private get _fCanvas(): FCanvasBase { + return this._fComponentStore.fCanvas!; + } + + public handle(request: MinimapCalculateViewBoxRequest): IRect { + return this._getRectForMinimapView(); + } + + private _getRectForMinimapView(): IRect { + const result = this._calculateViewBox(); + result.x = 0; + result.y = 0; + return result; + } + + private _calculateViewBox(): IRect { + return RectExtensions.div(RectExtensions.fromElement(this._fFlow!.hostElement), this._fCanvas.transform.scale); + } +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.request.ts b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.request.ts new file mode 100644 index 0000000..e0f6934 --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-calculate-view-box/minimap-calculate-view-box.request.ts @@ -0,0 +1,3 @@ +export class MinimapCalculateViewBoxRequest { + +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/index.ts b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/index.ts new file mode 100644 index 0000000..7701e84 --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/index.ts @@ -0,0 +1,4 @@ +export * from './minimap-draw-nodes.execution'; + +export * from './minimap-draw-nodes.request'; + diff --git a/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.execution.ts b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.execution.ts new file mode 100644 index 0000000..72eb130 --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.execution.ts @@ -0,0 +1,62 @@ +import { inject, Injectable } from '@angular/core'; +import { MinimapDrawNodesRequest } from './minimap-draw-nodes.request'; +import { FExecutionRegister, IExecution } from '@foblex/mediator'; +import { createSVGElement } from '../../../domain'; +import { FNodeBase, FNodeDirective } from '../../../f-node'; +import { IRect, RectExtensions, setRectToElement } from '@foblex/2d'; +import { FComponentsStore } from '../../../f-storage'; +import { BrowserService } from '@foblex/platform'; +import { FCanvasBase } from '../../../f-canvas'; +import { FFlowBase } from '../../../f-flow'; + +@Injectable() +@FExecutionRegister(MinimapDrawNodesRequest) +export class MinimapDrawNodesExecution implements IExecution { + + private _fBrowser = inject(BrowserService); + private _fComponentStore = inject(FComponentsStore); + + private get _fFlow(): FFlowBase | undefined { + return this._fComponentStore.fFlow; + } + + private get _fNodes(): FNodeBase[] { + return this._fComponentStore.fNodes; + } + + private get _fCanvas(): FCanvasBase { + return this._fComponentStore.fCanvas!; + } + + public handle(request: MinimapDrawNodesRequest): SVGRectElement[] { + return this._createMinimapNodeElements(request); + } + + private _createMinimapNodeElements(request: MinimapDrawNodesRequest): SVGRectElement[] { + return this._fNodes.map((x) => { + const element = this._createNodeElement(); + setRectToElement(this._getNodeRect(x), element); + this._applyClassList(element, x, x instanceof FNodeDirective); + return element; + }); + } + + private _createNodeElement(): SVGRectElement { + return createSVGElement('rect', this._fBrowser); + } + + private _getNodeRect(node: FNodeBase): IRect { + return RectExtensions.div(this._getNodeRectInFlow(node), this._fCanvas.transform.scale); + } + + private _getNodeRectInFlow(node: FNodeBase): IRect { + return RectExtensions.elementTransform(RectExtensions.fromElement(node.hostElement), this._fFlow!.hostElement); + } + + private _applyClassList(element: SVGRectElement, node: FNodeBase, isNode: boolean): void { + element.classList.add('f-component', isNode ? 'f-minimap-node' : 'f-minimap-group'); + if (node.isSelected()) { + element.classList.add('f-selected'); + } + } +} diff --git a/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.request.ts b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.request.ts new file mode 100644 index 0000000..877868a --- /dev/null +++ b/projects/f-flow/src/f-minimap/domain/minimap-draw-nodes/minimap-draw-nodes.request.ts @@ -0,0 +1,3 @@ +export class MinimapDrawNodesRequest { + +} diff --git a/projects/f-flow/src/f-minimap/domain/providers.ts b/projects/f-flow/src/f-minimap/domain/providers.ts index 0cb821b..6128591 100644 --- a/projects/f-flow/src/f-minimap/domain/providers.ts +++ b/projects/f-flow/src/f-minimap/domain/providers.ts @@ -1,6 +1,9 @@ import { MINIMAP_DRAG_PREPARATION_PROVIDERS } from './minimap-drag-preparation'; import { MINIMAP_DRAG_FINALIZE_PROVIDERS } from './minimap-drag-finalize'; import { CalculateFlowPointFromMinimapPointExecution } from './calculate-flow-point-from-minimap-point'; +import { MinimapDrawNodesExecution } from './minimap-draw-nodes'; +import { MinimapCalculateViewBoxExecution } from './minimap-calculate-view-box'; +import { MinimapCalculateSvgScaleAndViewBoxExecution } from './minimap-calculate-svg-scale-and-view-box'; export const F_MINIMAP_DRAG_AND_DROP_PROVIDERS = [ @@ -9,4 +12,10 @@ export const F_MINIMAP_DRAG_AND_DROP_PROVIDERS = [ ...MINIMAP_DRAG_FINALIZE_PROVIDERS, ...MINIMAP_DRAG_PREPARATION_PROVIDERS, + + MinimapDrawNodesExecution, + + MinimapCalculateSvgScaleAndViewBoxExecution, + + MinimapCalculateViewBoxExecution, ]; diff --git a/projects/f-flow/src/f-minimap/f-minimap-canvas.directive.ts b/projects/f-flow/src/f-minimap/f-minimap-canvas.directive.ts index dfb8d0d..cbb3992 100644 --- a/projects/f-flow/src/f-minimap/f-minimap-canvas.directive.ts +++ b/projects/f-flow/src/f-minimap/f-minimap-canvas.directive.ts @@ -1,77 +1,32 @@ import { - Directive, ElementRef, + Directive, ElementRef, inject, } from "@angular/core"; -import { FComponentsStore } from '../f-storage'; -import { - IRect, - RectExtensions -} from '@foblex/2d'; -import { FNodeBase, FNodeDirective } from '../f-node'; -import { BrowserService } from '@foblex/platform'; -import { createSVGElement } from '../domain'; -import { checkRectIsFinite } from './domain'; +import { FMediator } from '@foblex/mediator'; +import { MinimapDrawNodesRequest } from './domain'; @Directive({ selector: 'g[fMinimapCanvas]' }) export class FMinimapCanvasDirective { - public get hostElement(): SVGGElement { - return this.elementReference.nativeElement; - } + private _fMediator = inject(FMediator); - private get flowHost(): HTMLElement { - return this.fComponentsStore.flowHost; - } + private _elementReference = inject(ElementRef); - private get flowScale(): number { - return this.fComponentsStore.fCanvas!.transform.scale; - } - - constructor( - private elementReference: ElementRef, - private fComponentsStore: FComponentsStore, - private fBrowser: BrowserService - ) { + public get hostElement(): SVGGElement { + return this._elementReference.nativeElement; } public redraw(): void { - this.clearCanvas(); - this.fComponentsStore.fNodes.forEach((x) => this.renderNode(x)); - } - - private clearCanvas(): void { - this.hostElement.innerHTML = ''; - } + this._clearCanvas(); - private renderNode(node: FNodeBase): void { - const element = createSVGElement('rect', this.fBrowser); - this.configureNodeElement(element, node); - this.hostElement.appendChild(element); + this._fMediator.send(new MinimapDrawNodesRequest()) + .forEach((x) => { + this.hostElement.appendChild(x); + }); } - private configureNodeElement(element: SVGRectElement, node: FNodeBase): void { - this.setElementAttributes(element, this.getNodeRect(node)); - this.applyClassList(element, node, node instanceof FNodeDirective); - } - - private getNodeRect(node: FNodeBase): IRect { - const nodeRectInFlow = RectExtensions.elementTransform(RectExtensions.fromElement(node.hostElement), this.flowHost); - return RectExtensions.div(nodeRectInFlow, this.flowScale); - } - - private setElementAttributes(element: SVGRectElement, rect: IRect): void { - rect = checkRectIsFinite(rect); - element.setAttribute('x', rect.x.toString()); - element.setAttribute('y', rect.y.toString()); - element.setAttribute('width', rect.width.toString()); - element.setAttribute('height', rect.height.toString()); - } - - private applyClassList(element: SVGRectElement, node: FNodeBase, isNode: boolean): void { - element.classList.add('f-component', isNode ? 'f-minimap-node' : 'f-minimap-group'); - if (node.isSelected()) { - element.classList.add('f-selected'); - } + private _clearCanvas(): void { + this.hostElement.innerHTML = ''; } } diff --git a/projects/f-flow/src/f-minimap/f-minimap-flow.directive.ts b/projects/f-flow/src/f-minimap/f-minimap-flow.directive.ts index 04cce11..b6f62c7 100644 --- a/projects/f-flow/src/f-minimap/f-minimap-flow.directive.ts +++ b/projects/f-flow/src/f-minimap/f-minimap-flow.directive.ts @@ -1,95 +1,34 @@ import { - Directive, ElementRef, Input, + Directive, ElementRef, inject, Input, OnInit, } from "@angular/core"; -import { FComponentsStore } from '../f-storage'; -import { IRect, ISize, RectExtensions, SizeExtensions } from '@foblex/2d'; +import { setRectToViewBox } from '@foblex/2d'; import { FMediator } from '@foblex/mediator'; -import { checkRectIsFinite, FMinimapData } from './domain'; -import { GetNodesRectRequest } from '../domain'; +import { FMinimapData, IFMinimapScaleAndViewBox, MinimapCalculateSvgScaleAndViewBoxRequest } from './domain'; @Directive({ selector: 'svg[fMinimapFlow]' }) export class FMinimapFlowDirective { - public model: FMinimapData; - @Input() public fMinSize: number = 1000; - private get flowHost(): HTMLElement { - return this.fComponentsStore.flowHost; - } - - public get hostElement(): SVGSVGElement { - return this.elementReference.nativeElement; - } - - constructor( - private elementReference: ElementRef, - private fMediator: FMediator, - private fComponentsStore: FComponentsStore - ) { - this.model = new FMinimapData(this.hostElement); - } - - public update(): void { - const nodesRect = this.getProcessedNodesRect(); - const minimapRect = this.getMinimapRect(); - - const scale = this.calculateViewScale(nodesRect, minimapRect); - const viewBox = this.calculateViewBox(nodesRect, minimapRect, scale); - this.model = new FMinimapData(this.hostElement, scale, viewBox); - this.setViewBox(viewBox); - } - - private getProcessedNodesRect(): IRect { - const normalizedRect = this.normalizeRect(this.getNodesRect()); - return this.ensureMinimumSize(normalizedRect); - } + private _fMediator = inject(FMediator); - private getNodesRect(): IRect { - const rect = this.fMediator.send(new GetNodesRectRequest()) || RectExtensions.initialize(0, 0, 0, 0); - return RectExtensions.elementTransform(rect, this.flowHost) - } + private _elementReference = inject(ElementRef); - private getMinimapRect(): IRect { - return RectExtensions.elementTransform(RectExtensions.fromElement(this.hostElement), this.flowHost); + public get hostElement(): SVGSVGElement { + return this._elementReference.nativeElement; } - private normalizeRect(rect: IRect): IRect { - return RectExtensions.div(rect, this.fComponentsStore.fCanvas!.transform.scale); - } + public model: FMinimapData = new FMinimapData(this.hostElement); - private ensureMinimumSize(rect: IRect): IRect { - return RectExtensions.initialize( - rect.x - (Math.max(rect.width, this.fMinSize) - rect.width) / 2, - rect.y - (Math.max(rect.height, this.fMinSize) - rect.height) / 2, - Math.max(rect.width, this.fMinSize), - Math.max(rect.height, this.fMinSize) + public redraw(): void { + const { scale, viewBox} = this._fMediator.send( + new MinimapCalculateSvgScaleAndViewBoxRequest(this.hostElement, this.fMinSize) ); - } - - private calculateViewScale(nodesRect: IRect, minimapRect: IRect): number { - return Math.max(nodesRect.width / minimapRect.width, nodesRect.height / minimapRect.height); - } - - private calculateViewBox(nodesRect: IRect, minimapRect: IRect, scale: number): IRect { - return this.calculateCenteredViewBox(nodesRect, this.calculateViewSize(minimapRect, scale)); - } - - private calculateViewSize(minimapRect: IRect, scale: number): ISize { - return SizeExtensions.initialize(minimapRect.width * scale || 0, minimapRect.height * scale || 0); - } - - private calculateCenteredViewBox(nodesRect: IRect, viewSize: ISize): IRect { - const centeredX = nodesRect.x - (viewSize.width - nodesRect.width) / 2; - const centeredY = nodesRect.y - (viewSize.height - nodesRect.height) / 2; - return RectExtensions.initialize(centeredX, centeredY, viewSize.width, viewSize.height); - } + this.model = new FMinimapData(this.hostElement, scale, viewBox); - private setViewBox(viewBox: IRect): void { - viewBox = checkRectIsFinite(viewBox); - this.hostElement.setAttribute('viewBox', `${ viewBox.x } ${ viewBox.y } ${ viewBox.width } ${ viewBox.height }`); + setRectToViewBox(viewBox, this.hostElement); } } diff --git a/projects/f-flow/src/f-minimap/f-minimap-view.directive.ts b/projects/f-flow/src/f-minimap/f-minimap-view.directive.ts index cdffc1e..579d027 100644 --- a/projects/f-flow/src/f-minimap/f-minimap-view.directive.ts +++ b/projects/f-flow/src/f-minimap/f-minimap-view.directive.ts @@ -1,7 +1,7 @@ -import { Directive, ElementRef } from "@angular/core"; -import { FComponentsStore } from '../f-storage'; -import { IRect, RectExtensions } from '@foblex/2d'; -import { checkRectIsFinite } from './domain'; +import { Directive, ElementRef, inject } from "@angular/core"; +import { IRect, setRectToElement } from '@foblex/2d'; +import { FMediator } from '@foblex/mediator'; +import { MinimapCalculateViewBoxRequest } from './domain'; @Directive({ selector: 'rect[fMinimapView]', @@ -11,33 +11,18 @@ import { checkRectIsFinite } from './domain'; }) export class FMinimapViewDirective { - public get hostElement(): SVGRectElement { - return this.elementReference.nativeElement; - } - - private get flowScale(): number { - return this.fComponentsStore!.fCanvas!.transform.scale!; - } + private _fMediator = inject(FMediator); - constructor( - private elementReference: ElementRef, - private fComponentsStore: FComponentsStore - ) { - } - - public update(): void { - this._setAttributes(this._calculateViewBox()); - } + private _elementReference = inject(ElementRef); - private _calculateViewBox(): IRect { - return RectExtensions.div(RectExtensions.fromElement(this.fComponentsStore.flowHost), this.flowScale); + public get hostElement(): SVGGElement { + return this._elementReference.nativeElement; } - private _setAttributes(viewBox: IRect): void { - viewBox = checkRectIsFinite(viewBox); - this.hostElement.setAttribute('x', '0'); - this.hostElement.setAttribute('y', '0'); - this.hostElement.setAttribute('width', viewBox.width.toString()); - this.hostElement.setAttribute('height', viewBox.height.toString()); + public redraw(): void { + setRectToElement( + this._fMediator.send(new MinimapCalculateViewBoxRequest()), + this.hostElement + ); } } diff --git a/projects/f-flow/src/f-minimap/f-minimap.component.ts b/projects/f-flow/src/f-minimap/f-minimap.component.ts index 6c5648e..424ea1f 100644 --- a/projects/f-flow/src/f-minimap/f-minimap.component.ts +++ b/projects/f-flow/src/f-minimap/f-minimap.component.ts @@ -58,8 +58,8 @@ export class FMinimapComponent implements AfterViewInit, IFDragAndDropPlugin { if (!this._fBrowser.isBrowser()) { return; } - this.fMinimapFlow.update(); - this.fMinimapView.update(); + this.fMinimapFlow.redraw(); + this.fMinimapView.redraw(); this.fMinimapCanvas.redraw(); }