Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: directly override svgCanvas2D.getTextCss #3046

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions src/component/mxgraph/config/ShapeConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
import type { mxShape } from 'mxgraph';

import { ShapeBpmnElementKind } from '../../../model/bpmn/internal';
import { mxCellRenderer, mxConstants, mxSvgCanvas2D } from '../initializer';
import { mxCellRenderer } from '../initializer';
import {
BusinessRuleTaskShape,
CallActivityShape,
Expand Down Expand Up @@ -81,53 +81,6 @@ const registerShapes = (): void => {
*/
export default class ShapeConfigurator {
configureShapes(): void {
this.initMxSvgCanvasPrototype();
registerShapes();
}

private initMxSvgCanvasPrototype(): void {
// getTextCss is only used when creating foreignObject for label, so there is no impact on svg text that we use for Overlays.
// Analysis done for [email protected], still apply to [email protected]
mxSvgCanvas2D.prototype.getTextCss = function () {
const s = this.state;
const lh = mxConstants.ABSOLUTE_LINE_HEIGHT ? s.fontSize * mxConstants.LINE_HEIGHT + 'px' : mxConstants.LINE_HEIGHT * this.lineHeightCorrection;
let css =
'display: inline-block; font-size: ' +
s.fontSize +
'px; ' +
'font-family: ' +
s.fontFamily +
'; color: ' +
s.fontColor +
'; line-height: ' +
lh +
// START Fix for issue #920 (https://github.com/process-analytics/bpmn-visualization-js/issues/920)
// This cannot be generalized for all mxgraph use cases. For instance, in an editor mode, we should be able to edit the text by clicking on it.
// Setting to 'none' prevent to capture click.
'; pointer-events: none' +
// (this.pointerEvents ? this.pointerEventsValue : 'none') +
// END OF Fix for issue #920
'; ';

if ((s.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD) {
css += 'font-weight: bold; ';
}
if ((s.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC) {
css += 'font-style: italic; ';
}

const deco = [];
if ((s.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) {
deco.push('underline');
}
if ((s.fontStyle & mxConstants.FONT_STRIKETHROUGH) == mxConstants.FONT_STRIKETHROUGH) {
deco.push('line-through');
}
if (deco.length > 0) {
css += 'text-decoration: ' + deco.join(' ') + '; ';
}

return css;
};
}
}
21 changes: 20 additions & 1 deletion src/component/mxgraph/shape/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const overrideCreateSvgCanvas = function (shape: mxShape): void {
// The following is copied from the mxgraph mxShape implementation then converted to TypeScript and enriched for bpmn-visualization
// It is needed for adding the custom attributes that permits identification of the BPMN elements in the DOM
shape.createSvgCanvas = function () {
const canvas = new mxSvgCanvas2D(this.node, false);
// START bpmn-visualization CUSTOMIZATION
// use custom canvas implementation
const canvas = new SvgCanvas2D(this.node, false);
// END bpmn-visualization CUSTOMIZATION
canvas.strokeTolerance = this.pointerEvents ? this.svgStrokeTolerance : 0;
canvas.pointerEventsValue = this.svgPointerEvents;
const off = this.getSvgScreenOffset();
Expand Down Expand Up @@ -65,3 +68,19 @@ export const overrideCreateSvgCanvas = function (shape: mxShape): void {
return canvas;
};
};

class SvgCanvas2D extends mxSvgCanvas2D {
// getTextCss is only used when creating foreignObject for label, so there is no impact on svg text that we use for Overlays.
// Analysis done for [email protected], still apply to [email protected]
override getTextCss(): string {
const originalPointerEvents = this.pointerEvents;
// Fix for issue https://github.com/process-analytics/bpmn-visualization-js/issues/920
// This sets the "pointer-events" style property to "none" to avoid capturing the click.
// This cannot be generalized for all mxgraph use cases. For instance, in an editor mode, we should be able to edit the text by clicking on it.
this.pointerEvents = false;

const textCss = super.getTextCss();
this.pointerEvents = originalPointerEvents;
return textCss;
}
}
14 changes: 7 additions & 7 deletions test/integration/dom.container.div.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ describe.each`
it('DOM should contains BPMN elements when loading simple-start-task-end.bpmn', () => {
bpmnVisualization.load(readFileSync('../fixtures/bpmn/simple-start-task-end.bpmn'));

htmlElementLookup.expectStartEvent('StartEvent_1', ShapeBpmnEventDefinitionKind.NONE);
htmlElementLookup.expectTask('Activity_1');
htmlElementLookup.expectEndEvent('EndEvent_1', ShapeBpmnEventDefinitionKind.NONE);
htmlElementLookup.expectStartEvent('StartEvent_1', ShapeBpmnEventDefinitionKind.NONE, { label: 'Start Event 1' });
htmlElementLookup.expectTask('Activity_1', { label: 'Task 1' });
htmlElementLookup.expectEndEvent('EndEvent_1', ShapeBpmnEventDefinitionKind.NONE, { label: 'End Event 1' });
});

it('DOM should contains BPMN elements when loading model-complete-semantic.bpmn', () => {
bpmnVisualization.load(readFileSync('../fixtures/bpmn/model-complete-semantic.bpmn'));

htmlElementLookup.expectPool('participant_1_id');
htmlElementLookup.expectLane('lane_4_1_id');
htmlElementLookup.expectPool('participant_1_id', { label: 'Pool 1' });
htmlElementLookup.expectLane('lane_4_1_id', { label: 'Lane with child lanes' });

htmlElementLookup.expectStartEvent('start_event_signal_id', ShapeBpmnEventDefinitionKind.SIGNAL);
htmlElementLookup.expectIntermediateThrowEvent('intermediate_throw_event_message_id', ShapeBpmnEventDefinitionKind.MESSAGE);
htmlElementLookup.expectStartEvent('start_event_signal_id', ShapeBpmnEventDefinitionKind.SIGNAL, { label: 'Signal Start Event' });
htmlElementLookup.expectIntermediateThrowEvent('intermediate_throw_event_message_id', ShapeBpmnEventDefinitionKind.MESSAGE, { label: 'Throw Message Intermediate Event' });
});
});
15 changes: 9 additions & 6 deletions test/integration/helpers/html-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ export class HtmlElementLookup {
this.expectEventType(bpmnId, 'bpmn-start-event', bpmnEventDefinition, checks);
}

expectIntermediateThrowEvent(bpmnId: string, bpmnEventDefinition: ShapeBpmnEventDefinitionKind): void {
this.expectEventType(bpmnId, 'bpmn-intermediate-throw-event', bpmnEventDefinition);
expectIntermediateThrowEvent(bpmnId: string, bpmnEventDefinition: ShapeBpmnEventDefinitionKind, checks?: RequestedChecks): void {
this.expectEventType(bpmnId, 'bpmn-intermediate-throw-event', bpmnEventDefinition, checks);
}

expectEndEvent(bpmnId: string, bpmnEventDefinition: ShapeBpmnEventDefinitionKind, checks?: RequestedChecks): void {
Expand All @@ -74,8 +74,8 @@ export class HtmlElementLookup {
this.expectElement(bpmnId, expectSvgTask, ['bpmn-type-activity', 'bpmn-type-task', bpmnClass], checks);
}

expectTask(bpmnId: string): void {
this.expectTaskType(bpmnId, 'bpmn-task');
expectTask(bpmnId: string, checks?: RequestedChecks): void {
this.expectTaskType(bpmnId, 'bpmn-task', checks);
}

expectServiceTask(bpmnId: string, checks?: RequestedChecks): void {
Expand All @@ -94,8 +94,8 @@ export class HtmlElementLookup {
this.expectElement(bpmnId, expectSvgLane, ['bpmn-type-container', 'bpmn-lane'], checks);
}

expectPool(bpmnId: string): void {
this.expectElement(bpmnId, expectSvgPool, ['bpmn-type-container', 'bpmn-pool']);
expectPool(bpmnId: string, checks?: RequestedChecks): void {
this.expectElement(bpmnId, expectSvgPool, ['bpmn-type-container', 'bpmn-pool'], checks);
}

// ===========================================================================
Expand Down Expand Up @@ -169,6 +169,9 @@ export class HtmlElementLookup {

const labelLastDivElement = this.querySelector<HTMLElement>(this.bpmnQuerySelectors.labelLastDiv(bpmnId));
expect(labelLastDivElement.innerHTML).toEqual(label);
// Validate fix for https://github.com/process-analytics/bpmn-visualization-js/issues/920
expect(labelLastDivElement.style.pointerEvents).toBe('none');

const labelSvgGroup = this.querySelector<HTMLElement>(this.bpmnQuerySelectors.labelSvgGroup(bpmnId));
expectClassAttribute(labelSvgGroup, computeClassValue(bpmnClasses, ['bpmn-label', ...(additionalClasses ?? [])]));
}
Expand Down
Loading