Resize text boxes

Hello everyone,

I have a problem similar to Name of TextAnnotation resize eventhandler, but I think it is sufficiently different to warrant its own post:

Goal

I am trying to make the Text Boxes / Labels on all Elements, including on Flows, resizable. We often have rather large amounts of text there and while they do adapt in height, we would like to be able to change the width as well.
Generally speaking I would like to solve this with annotations instead of labels, but as far as I understood it bpmn.io does not support annotations on flows.

Approach

Generally we are using this code to make all elements resizable:

ResizeAllRules.prototype.init = function() {
  this.addRule('shape.resize', 1500, ({ shape }) => {
    return !is(shape, 'bpmn:SequenceFlow');
  });
};

Problem

Currently I have two problems:

  1. The label text does not follow the resizing. I can resize labels (except see below), but the text stays the same.

  2. The shape.resize-Rule does not apply to labels on flows. Labels on start events can be resized, but the text does not adapt.

What I’m looking for

I saw the solution to my first problem here. However, I do not know how to apply this to my application without forking bpmn.io. Can I overwrite / extend TextRenderer / BpmnRenderer somehow?

As for my second problem I’m at a bit of a loss: Why would the label for flows behave differently from the label for start events?

I did see this tutorial GitHub - bpmn-io/bpmn-js-example-custom-rendering: An example of creating custom rendering for bpmn-js, but it uses extend to modifiy the BaseRenderer, but I do not know how to transfer this to TextRenderer and BpmnRenderer, which are functions.

The TextRenderer is a didi service itself, so (theoretically) it should be overridable in the same fashion as with the BaseRenderer.

Did you already try that out? Did you get any problems?

As for my second problem I’m at a bit of a loss: Why would the label for flows behave differently from the label for start events?

We already have an issue for this. As a general result, we are currently not able to do this properly. However, the investigations / solution approach could be a good starting point.

I have now tried to extend the BpmnRenderer to create a custom version. However, I cannot use my custom renderer because it throws the following error

Error: No provider for "customBpmnRenderer"! (Resolving: customBpmnRenderer)

Here is my code:

// CustomBpmnRenderer.js
import BpmnRenderer from 'bpmn-js/lib/draw/BpmnRenderer';

export default class CustomBpmnRenderer extends BpmnRenderer {
	constructor(config, eventBus, styles, pathMap, canvas, textRenderer, bpmnRenderer) {
		super (config, eventBus, styles, pathMap, canvas, textRenderer, 1500);
		this.bpmnRenderer = bpmnRenderer;
	}

	getExternalLabelBounds(bounds, text) {

		var layoutedDimensions = textUtil.getDimensions(text, {
		  box: {
			width: !bounds.width ? 500 : bounds.width, //was hardcoded to 90
			height: !bounds.height ? 30 : bounds.height, //was hardcoded to 30
			x: bounds.width / 2 + bounds.x,
			y: bounds.height / 2 + bounds.y
		  },
		  style: externalStyle
		});
	
		// resize label shape to fit label text
		return {
		  x: Math.round(bounds.x + bounds.width / 2 - layoutedDimensions.width / 2),
		  y: Math.round(bounds.y),
		  width: Math.ceil(layoutedDimensions.width),
		  height: Math.ceil(layoutedDimensions.height)
		};
	
	  };
}

CustomBpmnRenderer.$inject = [
	'config.bpmnRenderer',
	'eventBus',
	'styles',
	'pathMap',
	'canvas',
	'textRenderer'
  ];
import CustomBpmnRenderer from './CustomBpmnRenderer';
//import CustomTextRenderer from './CustomTextRenderer';

export default {
  __init__: [ 'customBpmnRenderer' ],
  custpmBpmnRenderer: [ 'type', CustomBpmnRenderer ]
  //customTextRenderer: [ 'type', CustomTextRenderer ]
};

Then I import this module and add it to additionalModules.

Seems like there is a typo when defining your service: custpmBpmnRenderer

Ah, now that is embarrassing. I have corrected this error but still cannot achieve the results I want. I was looking into creating a codesandbox to illustrate my problem, when I came across another error in an example template. I have opened another thread and would come back to this one once I have managed to created the codesandbox.

I have now created a codesandbox based on the example provided. It includes a module resize, which allows to change the size of all elements except sequence flows and a module draw, which should apply this to text labels. However, it does not work. The changes I make in my custom draw module to not seem to override the default behaviour. I presumably misunderstood something from the example on overriding, but I can’t for the life of me figure it out.

Make sure you initialize both custom renderers correctly

import CustomBpmnRenderer from './CustomBpmnRenderer';
import CustomTextRenderer from './CustomTextRenderer';

export default {
  __init__: [ 'customBpmnRenderer', 'customTextRenderer'],
  customBpmnRenderer: [ 'type', CustomBpmnRenderer ],
  customTextRenderer: [ 'type', CustomTextRenderer ]
};

When you want to use your custom text renderer inside your custom bpmn renderer, you also have to include this one

CustomBpmnRenderer.$inject = [
  "config.bpmnRenderer",
  "eventBus",
  "styles",
  "pathMap",
  "canvas",
  "customTextRenderer"
];

I have corrected both, but the problem remains. It seems to me that the overriding does not work, because even if I let CustomBpmnRenderer.renderExternalLabel immediately throw an error, the labels are rendered.