Skip to content

Commit

Permalink
grid dragging with connections
Browse files Browse the repository at this point in the history
  • Loading branch information
siarheihuzarevich committed Jan 29, 2025
1 parent f77a40a commit da48fbc
Show file tree
Hide file tree
Showing 121 changed files with 1,253 additions and 1,122 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<f-flow fDraggable [vCellSize]="32" [hCellSize]="32" (fLoaded)="onLoaded()">
<f-flow fDraggable
[vCellSize]="32"
[hCellSize]="32"
[fCellSizeWhileDragging]="adjustCellSizeWhileDragging"
(fLoaded)="onLoaded()">
<f-background>
<f-rect-pattern [vSize]="32" [hSize]="32"></f-rect-pattern>
</f-background>
Expand All @@ -8,3 +12,8 @@
<div fNode [fNodePosition]="{ x: 192, y: 96 }" fNodeInput fInputId="input1" fDragHandle>I'm a node</div>
</f-canvas>
</f-flow>
<div class="toolbar">
<f-checkbox [checked]="adjustCellSizeWhileDragging"
(change)="onAdjustCellSizeWhileDraggingChange($event)">Adjust cell size while dragging
</f-checkbox>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
@include flow-common.node;
}

.toolbar {
@include flow-common.toolbar;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { FCanvasComponent, FFlowModule } from '@foblex/flow';
import { FCheckboxComponent } from '@foblex/m-render';

@Component({
selector: 'grid-system-example',
Expand All @@ -9,14 +10,21 @@ import { FCanvasComponent, FFlowModule } from '@foblex/flow';
standalone: true,
imports: [
FFlowModule,
FCheckboxComponent,
]
})
export class GridSystemExampleComponent {

protected adjustCellSizeWhileDragging: boolean = false;

@ViewChild(FCanvasComponent, { static: true })
public fCanvas!: FCanvasComponent;
protected fCanvas!: FCanvasComponent;

public onLoaded(): void {
protected onLoaded(): void {
this.fCanvas.resetScaleAndCenter(false);
}

protected onAdjustCellSizeWhileDraggingChange(event: boolean): void {
this.adjustCellSizeWhileDragging = event;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@

<div fNode fDragHandle
[fNodePosition]="{ x: 150, y: 100 }" (fNodeSizeChange)="onNodeSizeChanged($event)">
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.LEFT"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.LEFT_TOP"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.TOP"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.RIGHT_TOP"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.LEFT_BOTTOM"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.RIGHT"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.RIGHT_BOTTOM"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.BOTTOM"></div>
<div fResizeHandle [fResizeHandleType]="eResizeHandleType.LEFT_BOTTOM"></div>
<div class="node-content">
Node with all ResizeHandles
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,51 @@
background-color: var(--node-background-color);
border: 1px solid var(--node-border-color);

&.f-resize-handle-left {
top: calc(50% - 6px);
left: -6px;
cursor: col-resize;
}

&.f-resize-handle-left-top {
top: -6px;
left: -6px;
cursor: nwse-resize;
}

&.f-resize-handle-top {
top: -6px;
left: calc(50% - 6px);
cursor: row-resize;
}

&.f-resize-handle-right-top {
top: -6px;
right: -6px;
cursor: nesw-resize;
}

&.f-resize-handle-left-bottom {
bottom: -6px;
left: -6px;
cursor: nesw-resize;
&.f-resize-handle-right {
top: calc(50% - 6px);
right: -6px;
cursor: col-resize;
}

&.f-resize-handle-right-bottom {
bottom: -6px;
right: -6px;
cursor: nwse-resize;
}

&.f-resize-handle-bottom {
bottom: -6px;
left: calc(50% - 6px);
cursor: row-resize;
}

&.f-resize-handle-left-bottom {
bottom: -6px;
left: -6px;
cursor: nesw-resize;
}
}
2 changes: 1 addition & 1 deletion projects/f-flow/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foblex/flow",
"version": "17.1.0",
"version": "17.1.1",
"description": "An Angular library designed to simplify the creation and manipulation of dynamic flow. Provides components for flows, nodes, and connections, automating node manipulation and inter-node connections.",
"main": "index.js",
"types": "index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class RedrawConnectionsExecution implements IExecution<RedrawConnectionsR
connection.setLine(line.point1, output.fConnectableSide, line.point2, input.fConnectableSide);

connection.initialize();
connection.isSelected() ? connection.select() : null;
connection.isSelected() ? connection.markAsSelected() : null;
}

private getLine(output: FConnectorBase, input: FConnectorBase, connection: FConnectionBase): ILine {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GetAllCanBeConnectedInputsAndRectsRequest } from './get-all-can-be-connected-inputs-and-rects.request';
import { inject, Injectable } from '@angular/core';
import { FExecutionRegister, FMediator, IExecution } from '@foblex/mediator';
import { FConnectorBase, FNodeOutletDirective, FNodeOutputDirective } from '../../../f-connectors';
import { FConnectorBase, FNodeOutletBase, FNodeOutputBase } from '../../../f-connectors';
import { FComponentsStore } from '../../../f-storage';
import { IConnectorAndRect } from '../i-connector-and-rect';
import { GetConnectorAndRectRequest } from '../get-connector-and-rect';
Expand All @@ -19,26 +19,26 @@ export class GetAllCanBeConnectedInputsAndRectsExecution
}

public handle(payload: GetAllCanBeConnectedInputsAndRectsRequest): IConnectorAndRect[] {
return this._getCanBeConnectedInputs(payload.fOutput).map((x) => {
return this._getCanBeConnectedInputs(payload.fOutputOrOutlet).map((x) => {
return this._fMediator.execute(new GetConnectorAndRectRequest(x));
});
}

private _getCanBeConnectedInputs(fOutput: FNodeOutputDirective | FNodeOutletDirective): FConnectorBase[] {
private _getCanBeConnectedInputs(fOutputOrOutlet: FNodeOutputBase | FNodeOutletBase): FConnectorBase[] {
let fInputs: FConnectorBase[] = [];
if (fOutput.canBeConnectedInputs?.length) {
fInputs = this._fInputs.filter((x) => fOutput.canBeConnectedInputs.includes(x.fId));
if (fOutputOrOutlet.canBeConnectedInputs?.length) {
fInputs = this._fInputs.filter((x) => fOutputOrOutlet.canBeConnectedInputs.includes(x.fId));
} else {
fInputs = this._fInputs.filter((x) => x.canBeConnected);

if(!fOutput.isSelfConnectable) {
fInputs = this._filterSelfConnectable(fInputs, fOutput);
if(!fOutputOrOutlet.isSelfConnectable) {
fInputs = this._filterSelfConnectable(fInputs, fOutputOrOutlet);
}
}
return fInputs;
}

private _filterSelfConnectable(fInputs: FConnectorBase[], fOutput: FConnectorBase): FConnectorBase[] {
return fInputs.filter((x) => fOutput.fNodeId !== x.fNodeId);
private _filterSelfConnectable(fInputs: FConnectorBase[], fOutputOrOutlet: FConnectorBase): FConnectorBase[] {
return fInputs.filter((x) => fOutputOrOutlet.fNodeId !== x.fNodeId);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { FNodeOutletDirective, FNodeOutputDirective } from '../../../f-connectors';
import { FNodeOutletBase, FNodeOutputBase } from '../../../f-connectors';

export class GetAllCanBeConnectedInputsAndRectsRequest {

constructor(
public fOutput: FNodeOutputDirective | FNodeOutletDirective,
public fOutputOrOutlet: FNodeOutputBase | FNodeOutletBase,
) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class PrepareDragSequenceExecution implements IExecution<PrepareDragSeque
public handle(request: PrepareDragSequenceRequest): void {
this._callPrepareDragSequence();

this._fMediator.send<void>(new StartDragSequenceRequest());
this._fMediator.execute<void>(new StartDragSequenceRequest());
}

private _callPrepareDragSequence(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { F_CSS_CLASS } from '../../css-cls';
export class StartDragSequenceExecution implements IExecution<StartDragSequenceRequest, void> {

private _fMediator = inject(FMediator);

private _fComponentsStore = inject(FComponentsStore);

private get _hostElement(): HTMLElement {
Expand Down
11 changes: 11 additions & 0 deletions projects/f-flow/src/domain/f-event-trigger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export type FEventTrigger = (event: TriggerEvent) => boolean;

export type TriggerEvent = MouseEvent | TouchEvent | WheelEvent;

export function isValidEventTrigger(event: TriggerEvent, fTrigger: FEventTrigger): boolean {
return fTrigger(event);
}

export function defaultEventTrigger(event: TriggerEvent): boolean {
return true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class UpdateNodeWhenStateOrSizeChangedExecution
stateChanges
).pipe(notifyOnStart(), debounceTime(10)).listen(request.destroyRef, () => {
this._calculateConnectorsConnectableSide(connectors, hostElement);
this._fMediator.send<void>(new NotifyDataChangedRequest());
this._fMediator.execute<void>(new NotifyDataChangedRequest());
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { FMediator } from '@foblex/mediator';
import { ClearSelectionRequest } from './clear-selection.request';
import { ClearSelectionExecution } from './clear-selection.execution';
import { setupTestModule } from '../../test-setup';
import { ICanChangeSelection } from '../../../mixins';
import { ISelectable } from '../../../mixins';
import { FDraggableDataContext } from '../../../f-draggable';

export const MOCK_SELECTABLE_ITEM: ICanChangeSelection = {
export const MOCK_SELECTABLE_ITEM: ISelectable = {
fId: '1',
fSelectionDisabled: false,
hostElement: document.createElement('svg'),
select: jasmine.createSpy('select'),
deselect: jasmine.createSpy('deselect'),
markAsSelected: jasmine.createSpy('markAsSelected'),
unmarkAsSelected: jasmine.createSpy('unmarkAsSelected'),
isSelected: jasmine.createSpy('isSelected').and.returnValue(true)
};

Expand All @@ -32,7 +32,7 @@ describe('ClearSelectionExecution', () => {
expect(fDraggableDataContext.selectedItems.length).toBe(2);
expect(fDraggableDataContext.isSelectedChanged).toBe(false);

fMediator.send<void>(new ClearSelectionRequest());
fMediator.execute<void>(new ClearSelectionRequest());
expect(fDraggableDataContext.selectedItems.length).toBe(0);
expect(fDraggableDataContext.isSelectedChanged).toBe(true);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { ClearSelectionRequest } from './clear-selection.request';
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { FExecutionRegister, IExecution } from '@foblex/mediator';
import { FDraggableDataContext } from '../../../f-draggable';

@Injectable()
@FExecutionRegister(ClearSelectionRequest)
export class ClearSelectionExecution implements IExecution<ClearSelectionRequest, void> {

constructor(
private fDraggableDataContext: FDraggableDataContext,
) {
}
private _fDraggableDataContext = inject(FDraggableDataContext);

public handle(request: ClearSelectionRequest): void {
this.fDraggableDataContext.selectedItems.forEach((x) => x.deselect());
this.fDraggableDataContext.selectedItems = [];
this.fDraggableDataContext.isSelectedChanged = true;
this._fDraggableDataContext.selectedItems.forEach((x) => x.unmarkAsSelected());
this._fDraggableDataContext.selectedItems = [];
this._fDraggableDataContext.isSelectedChanged = true;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject, Injectable } from '@angular/core';
import { IRect, ITransformModel, RectExtensions } from '@foblex/2d';
import { ICanBeSelected } from './i-can-be-selected';
import { ICanBeSelectedElementAndRect } from './i-can-be-selected-element-and-rect';
import { GetCanBeSelectedItemsRequest } from './get-can-be-selected-items-request';
import { FNodeBase } from '../../../f-node';
import { FConnectionBase } from '../../../f-connection';
Expand All @@ -11,10 +11,11 @@ import { GetNormalizedElementRectRequest } from '../../get-normalized-element-re

@Injectable()
@FExecutionRegister(GetCanBeSelectedItemsRequest)
export class GetCanBeSelectedItemsExecution implements IExecution<void, ICanBeSelected[]> {
export class GetCanBeSelectedItemsExecution implements IExecution<void, ICanBeSelectedElementAndRect[]> {

private _fMediator = inject(FMediator);
private _fComponentsStore = inject(FComponentsStore);
private _fDraggableDataContext = inject(FDraggableDataContext);

private get fNodes(): FNodeBase[] {
return this._fComponentsStore.fNodes;
Expand All @@ -28,34 +29,29 @@ export class GetCanBeSelectedItemsExecution implements IExecution<void, ICanBeSe
return this._fComponentsStore.fCanvas!.transform;
}

constructor(
private fDraggableDataContext: FDraggableDataContext,
) {
}

public handle(): ICanBeSelected[] {
public handle(): ICanBeSelectedElementAndRect[] {
return [ ...this.getNodesWithRects(), ...this.getConnectionsWithRects() ].filter((x) => {
return !this.fDraggableDataContext.selectedItems.includes(x.element);
return !this._fDraggableDataContext.selectedItems.includes(x.element);
});
}

private getNodesWithRects(): ICanBeSelected[] {
private getNodesWithRects(): ICanBeSelectedElementAndRect[] {
return this.fNodes.filter((x) => !x.fSelectionDisabled).map((x) => {
return {
element: x,
rect: RectExtensions.mult(
fRect: RectExtensions.mult(
this._fMediator.send<IRect>(new GetNormalizedElementRectRequest(x.hostElement, false)),
this.transform.scale
)
};
});
}

private getConnectionsWithRects(): ICanBeSelected[] {
private getConnectionsWithRects(): ICanBeSelectedElementAndRect[] {
return this.fConnections.filter((x) => !x.fSelectionDisabled).map((x) => {
return {
element: x,
rect: RectExtensions.mult(
fRect: RectExtensions.mult(
this._fMediator.send<IRect>(new GetNormalizedElementRectRequest(x.boundingElement, false)),
this.transform.scale
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IRect } from '@foblex/2d';
import { ISelectable } from '../../../mixins';

export interface ICanBeSelectedElementAndRect {

element: ISelectable;

fRect: IRect;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export * from './get-can-be-selected-items.execution';

export * from './get-can-be-selected-items-request';

export * from './i-can-be-selected';
export * from './i-can-be-selected-element-and-rect';
Loading

0 comments on commit da48fbc

Please sign in to comment.