Skip to content

Commit

Permalink
experimental implemenation
Browse files Browse the repository at this point in the history
Issue #315
  • Loading branch information
rsoika committed Jan 17, 2024
1 parent 2190ed0 commit c9acbcf
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 175 deletions.
33 changes: 33 additions & 0 deletions open-bpmn.glsp-client/open-bpmn-glsp/css/helper-lines.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/********************************************************************************
* Copyright (c) 2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

.helper-line {
pointer-events: none;
stroke: red;
stroke-width: 1px;
opacity: 1;
}

.selection-bounds {
pointer-events: none;
fill: blue;
fill-opacity: 0.05;
stroke-linejoin: miter;
stroke-linecap: round;
stroke: darkblue;
stroke-width: 1px;
stroke-dasharray: 2;
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,57 +13,100 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
GridSnapper,
IFeedbackActionDispatcher,
ISelectionListener,
MoveFinishedEventAction, MoveInitializedEventAction,
SelectionService,
SetBoundsFeedbackAction
} from '@eclipse-glsp/client';
import {
Action,
DisposableCollection,
GModelElement,
GModelRoot,
IActionHandler,
ISnapper,
IFeedbackActionDispatcher,
ISelectionListener,
MoveAction,
MoveFinishedEventAction, MoveInitializedEventAction,
Point,
SelectionService,
SetBoundsAction,
SetBoundsFeedbackAction,
TYPES
} from '@eclipse-glsp/sprotty';
} from '@eclipse-glsp/client';


import { inject, injectable, optional, postConstruct } from 'inversify';
// import { IFeedbackActionDispatcher } from '../../base/feedback/feedback-action-dispatcher';
// import { ISelectionListener, SelectionService } from '../../base/selection-service';
// import { SetBoundsFeedbackAction } from '../bounds/set-bounds-feedback-command';
// import { GridSnapper } from '../change-bounds/snap';
// import { MoveFinishedEventAction, MoveInitializedEventAction } from '../tools/change-bounds/change-bounds-tool-feedback';
import { DrawHelperLinesFeedbackAction, RemoveHelperLinesFeedbackAction, ViewportLineType } from './bpmn-helper-line-feedback';

import {
AlignmentElementFilter,
DEFAULT_ALIGNABLE_ELEMENT_FILTER,
DEFAULT_DEBUG,
DEFAULT_ELEMENT_LINES,
DEFAULT_EPSILON,
DEFAULT_VIEWPORT_LINES,
DrawHelperLinesFeedbackAction,
RemoveHelperLinesFeedbackAction,
ViewportLineType
} from './bpmn-helper-line-feedback';
import { IHelperLineManager } from './bpmn-helper-line-manager';
import { Direction, HelperLineType } from './model';

export interface IHelperLineOptions {
/**
* A list of helper line types that should be rendered when elements are aligned.
* Defaults to all possible alignments.
*/
elementLines?: HelperLineType[];
/**
* A list of helper line types that should be rendered when an element is aligned with the viewport.
* Defaults to middle and center alignment.
*/
viewportLines?: ViewportLineType[];
/**
* The minimum difference between two coordinates
* Defaults to 1.
*/
alignmentEpsilon?: number;
/**
* A filter that is applied to determine on which elements the alignment calculation is performed.
* By default all top-level bounds-aware, non-routable elements that are visible on the canvas are considered.
*/
alignmentElementFilter?: AlignmentElementFilter;
/**
* The minimum move delta that is necessary for an element to break through a helper line.
* Defaults to { x: 1, y: 1 } whereas the x represents the horizontal distance and y represents the vertical distance.
*/
minimumMoveDelta?: Point;

/**
* Produces debug output.
* Defaults to false.
*/
debug?: boolean;
}

export const DEFAULT_MOVE_DELTA = { x: 1, y: 1 };

export const DEFAULT_HELPER_LINE_OPTIONS: Required<IHelperLineOptions> = {
elementLines: DEFAULT_ELEMENT_LINES,
viewportLines: DEFAULT_VIEWPORT_LINES,
alignmentEpsilon: DEFAULT_EPSILON,
alignmentElementFilter: DEFAULT_ALIGNABLE_ELEMENT_FILTER,
minimumMoveDelta: DEFAULT_MOVE_DELTA,
debug: DEFAULT_DEBUG
};

@injectable()
export class HelperLineManager implements IActionHandler, ISelectionListener, IHelperLineManager {
@inject(TYPES.IFeedbackActionDispatcher) protected feedbackDispatcher: IFeedbackActionDispatcher;
@inject(SelectionService) protected selectionService: SelectionService;
@optional() @inject(TYPES.ISnapper) protected snapper?: ISnapper;
@optional() @inject(TYPES.IHelperLineOptions) protected userOptions?: IHelperLineOptions;

protected snapSize = { x: 10, y: 10 };
protected options: Required<IHelperLineOptions>;
protected feedback: DisposableCollection = new DisposableCollection();

protected elementLines?: HelperLineType[];
protected viewportLines?: ViewportLineType[];
protected alignmentEpsilon?: number;

@postConstruct()
protected init(): void {
this.options = { ...DEFAULT_HELPER_LINE_OPTIONS, ...this.userOptions };
this.selectionService.onSelectionChanged(change =>
this.selectionChanged(change.root, change.selectedElements, change.deselectedElements)
);
if (this.snapper instanceof GridSnapper) {
console.log('--------__> NOT helloe ich setzte irgendwas mit snap');
//this.snapSize = { x: this.snapper.grid.x * 2, y: this.snapper.grid.y * 2 };
}
}

handle(action: Action): void {
Expand Down Expand Up @@ -99,16 +142,10 @@ export class HelperLineManager implements IActionHandler, ISelectionListener, IH
}

protected createHelperLineFeedback(elementIds: string[]): DrawHelperLinesFeedbackAction {
return DrawHelperLinesFeedbackAction.create({
elementIds,
elementLines: this.elementLines,
viewportLines: this.viewportLines,
alignmentEpsilon: this.alignmentEpsilon
});
return DrawHelperLinesFeedbackAction.create({ elementIds, ...this.options });
}

protected handleSetBoundsAction(action: SetBoundsAction | SetBoundsFeedbackAction): void {
console.log('set bounds action');
const elementIds = action.bounds.map(bound => bound.elementId);
const feedback = this.createHelperLineFeedback(elementIds);
this.feedback.push(this.feedbackDispatcher.registerFeedback(this, [feedback], [RemoveHelperLinesFeedbackAction.create()]));
Expand All @@ -118,7 +155,12 @@ export class HelperLineManager implements IActionHandler, ISelectionListener, IH
this.feedback.dispose();
}

getHelperLineSnapping(target: GModelElement, isSnap: boolean, direction: Direction): number {
return direction === Direction.Left || direction === Direction.Right ? this.snapSize.x : this.snapSize.y;
getMinimumMoveDelta(element: GModelElement, isSnap: boolean, direction: Direction): number {
if (!isSnap) {
return 0;
}
return direction === Direction.Left || direction === Direction.Right
? this.options.minimumMoveDelta.x
: this.options.minimumMoveDelta.y;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@ import { GModelElement } from '@eclipse-glsp/sprotty';
import { Direction } from './model';

export interface IHelperLineManager {
getHelperLineSnapping(target: GModelElement, isSnap: boolean, direction: Direction): number;
/**
* Calculates the minimum move delta that is necessary to break through a helper line.
*
* @param element element that is being moved
* @param isSnap whether snapping is active or not
* @param direction direction in which the target element is moving
*/
getMinimumMoveDelta(element: GModelElement, isSnap: boolean, direction: Direction): number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,20 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import {
MoveFinishedEventAction, MoveInitializedEventAction,
SetBoundsFeedbackAction
} from '@eclipse-glsp/client';
import {
FeatureModule,
MoveAction,
MoveFinishedEventAction, MoveInitializedEventAction,
SetBoundsAction,
SetBoundsFeedbackAction,
TYPES,
bindAsService,
configureActionHandler,
configureCommand,
configureModelElement
} from '@eclipse-glsp/sprotty';
} from '@eclipse-glsp/client';


// import { SetBoundsFeedbackAction } from '../bounds/set-bounds-feedback-command';
// import { MoveFinishedEventAction, MoveInitializedEventAction } from '../tools/change-bounds/change-bounds-tool-feedback';
import { DrawHelperLinesFeedbackCommand, RemoveHelperLinesFeedbackCommand } from './bpmn-helper-line-feedback';
import { HelperLineManager } from './bpmn-helper-line-manager-default';
import { HELPER_LINE, HelperLine, SELECTION_BOUNDS, SelectionBounds } from './model';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { Args, Bounds, GChildElement, GModelElement, GShapeElement, Point } from '@eclipse-glsp/sprotty';
import { v4 as uuid } from 'uuid';
// import { ArgsAware } from '../../base/args-feature';
// import { ResizeHandleLocation } from '../change-bounds/model';
import {
Args,
ArgsAware,
Bounds, GChildElement, GModelElement, GShapeElement, Point,
ResizeHandleLocation
} from '@eclipse-glsp/client';



import { v4 as uuid } from 'uuid';
export const HelperLineType = {
Left: 'left',
Right: 'right',
Expand Down
60 changes: 47 additions & 13 deletions open-bpmn.glsp-client/open-bpmn-glsp/src/bpmn-helperlines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ import {
} from '@eclipse-glsp/client';
import {
EventNode,
LabelNode,
TaskNode,
isBPMNLabelNode,
isBPMNNode,
isBoundaryEvent,
isEventNode,
isGatewayNode,
isLaneDivider,
isTaskNode
} from '@open-bpmn/open-bpmn-model';
Expand Down Expand Up @@ -117,6 +117,40 @@ export class BPMNElementSnapper implements ISnapper {
if (isBoundaryEvent(element)) {
snapPoint = this.findBoundarySnapPoint(element, position);
} else {


if (isTaskNode(element)) {

snapPoint = {
x: Math.round(position.x / 10) * 10,
y: Math.round(position.y / 10) * 10
};
console.log('.. snap task: position= ' + position.x + ',' + position.y + ' snap= ' + snapPoint.x + ',' + snapPoint.y);
return snapPoint;
}
if (isGatewayNode(element)) {
// center snap...
return {
x: Math.round((position.x + 0.5 * element.bounds.width) / 5) * 5 - 0.5 * element.bounds.width,
y: Math.round((position.y + 0.5 * element.bounds.height) / 5) * 5 - 0.5 * element.bounds.height
};

}

if (isEventNode(element)) {
// center snap...
snapPoint = {
x: Math.round((position.x + 0.5 * element.bounds.width) / 5) * 5 - 0.5 * element.bounds.width,
y: Math.round((position.y + 0.5 * element.bounds.height) / 5) * 5 - 0.5 * element.bounds.height
};
console.log('.. snap event: position= ' + position.x + ',' + position.y + ' snap= ' + snapPoint.x + ',' + snapPoint.y);
return snapPoint;

}




// find default snap position
snapPoint = this.findSnapPoint(element);
// if a snapPoint was found and this snapPoint is still in the snapRange,
Expand All @@ -133,17 +167,17 @@ export class BPMNElementSnapper implements ISnapper {
}

// fix BPMNLabel offset (only needed or Elements with a separate label)?
if (isBPMNLabelNode(element)) {
const xOffset = snapPoint.x - position.x;
const yOffset = snapPoint.y - position.y;
const label: any = element.root.index.getById(element.id + '_bpmnlabel');
if (label instanceof LabelNode) {
// fix offset of the lable position....
const ly = label.position.y + yOffset;
const lx = label.position.x + xOffset;
label.position = { x: lx, y: ly };
}
}
// if (isBPMNLabelNode(element)) {
// const xOffset = snapPoint.x - position.x;
// const yOffset = snapPoint.y - position.y;
// const label: any = element.root.index.getById(element.id + '_bpmnlabel');
// if (label instanceof LabelNode) {
// // fix offset of the lable position....
// const ly = label.position.y + yOffset;
// const lx = label.position.x + xOffset;
// label.position = { x: lx, y: ly };
// }
// }
return snapPoint;
}

Expand Down
Loading

0 comments on commit c9acbcf

Please sign in to comment.