Skip to content

Commit

Permalink
fix(layout.PortLabel): fix passing of label.position.args.attrs in in…
Browse files Browse the repository at this point in the history
…side, outside, radial layouts (#2282)
  • Loading branch information
zbynekstara authored Aug 1, 2023
1 parent 690e84b commit 2b82631
Show file tree
Hide file tree
Showing 3 changed files with 1,294 additions and 72 deletions.
95 changes: 57 additions & 38 deletions docs/src/joint/api/layout/PortLabel.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@

Port label layout functions calculate port label positions relatively to port positions.

### Pre-defined port label layouts

#### On Sides

Simple label layout suitable for rectangular shapes. It places the label on arbitrary side of a port.

Simple label layout suitable for rectangular shapes. It places the label on arbitrary side of a port. The `args` object is optional.

<table>
<tr>
<td><b>name</b></td>
<td><i>string</i></td>
<td>
Can be either `left`, `right`, `bottom`, `top`.
Can be either <code>'left'</code>, <code>'right'</code>, <code>'top'</code>, or <code>'bottom'</code>.
</td>
</tr>
<tr>
<td><b>args</b></td>
<td><i>object | string</i></td>
<td><i>object</i></td>
<td>
<table>
<tr>
<td><b>x</b></td>
<td>number</td>
<td>Overrides the `x` value calculated by the layout function</td>
<td>Overrides the <code>x</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>y</b></td>
<td>number</td>
<td>Overrides the `y` value calculated by the layout function</td>
<td>Overrides the <code>y</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>angle</b></td>
<td>number</td>
<td>The port label rotation angle.</td>
<td>The port label rotation angle (in degrees in clockwise direction).</td>
</tr>
<tr>
<td><b>attrs</b></td>
<td>number</td>
<td>JointJS style attribute applied on label's DOM element and its children. The same notation as the `attrs` property on [`Element`](#dia.Element.intro.presentation).</td>
<td>object</td>
<td>JointJS-style attributes applied on label's DOM element and its children. The same notation as the <code>attrs</code> property on <a href="#dia.Element.intro.presentation">Element</a>. Overridden by port group <code>attrs</code>, if provided.</td>
</tr>
</table>
</td>
Expand All @@ -62,37 +60,51 @@ label: {

#### Inside/Outside

Places the label inside or outside of a rectangular shape. Where 'oriented' versions rotate the text towards the element center.
Places the label inside or outside of a rectangular shape. Where 'oriented' versions rotate the text towards the element center. The `args` object is optional.

<table>
<tr>
<td><b>name</b></td>
<td><i>string</i></td>
<td>
Can be either `inside`, `outside`, `insideOriented`, `outsideOriented`.
Can be either <code>'inside'</code>, <code>'outside'</code>, <code>'insideOriented'</code>, or <code>'outsideOriented'</code>.
</td>
</tr>
<tr>
<td><b>args</b></td>
<td><i>object | string</i></td>
<td><i>object</i></td>
<td>
<table>
<tr>
<td><b>offset</b></td>
<td>number</td>
<td>Offset in direction from the shape's center.</td>
<td>Offset in direction from the shape's center. Overridden by <code>x</code> and <code>y</code> values, if provided.</td>
</tr>
<tr>
<td><b>attrs</b></td>
<td><b>x</b></td>
<td>number</td>
<td>JointJS style attribute applied on label's DOM element and its children. The same notation as the `attrs` property on [`Element`](#dia.Element.intro.presentation).</td>
<td>Overrides the <code>x</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>y</b></td>
<td>number</td>
<td>Overrides the <code>y</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>angle</b></td>
<td>number</td>
<td>The port label rotation angle (in degrees in clockwise direction). Overrides the value calculated by the <code>'insideOriented'</code> and <code>'outsideOriented'</code> layout functions.</td>
</tr>
<tr>
<td><b>attrs</b></td>
<td>object</td>
<td>JointJS-style attributes applied on label's DOM element and its children. The same notation as the <code>attrs</code> property on <a href="#dia.Element.intro.presentation">Element</a>. Overridden by port group <code>attrs</code>, if provided.</td>
</tr>
</table>
</td>
</tr>
</table>


```javascript

label: {
Expand All @@ -107,39 +119,51 @@ label: {
#### Radial
Places the label outside of a circular shape. Where the 'oriented' version rotates the text towards the element center.
Places the label outside of a circular shape. Where the 'oriented' version rotates the text towards the element center. The `args` object is optional.
<table>
<tr>
<td><b>name</b></td>
<td><i>string</i></td>
<td>
Can be either `radial`, `radialOriented`.
Can be either <code>'radial'</code>, or <code>'radialOriented'</code>.
</td>
</tr>
<tr>
<td><b>args</b></td>
<td><i>object | string</i></td>
<td><i>object</i></td>
<td>
<table>
<tr>
<td><b>offset</b></td>
<td>number</td>
<td>Offset in direction from the shape's center.</td>
<td>Offset in direction from the shape's center. Overridden by <code>x</code> and <code>y</code> values, if provided.</td>
</tr>
<tr>
<td><b>x</b></td>
<td>number</td>
<td>Overrides the <code>x</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>y</b></td>
<td>number</td>
<td>Overrides the <code>y</code> value calculated by the layout function.</td>
</tr>
<tr>
<td><b>angle</b></td>
<td>number</td>
<td>The port label rotation angle (in degrees in clockwise direction). Overrides the value calculated by the <code>'radialOriented'</code> layout function.</td>
</tr>
<tr>
<td><b>attrs</b></td>
<td>number</td>
<td>JointJS style attribute applied on label's DOM element and its children. The same notation as the `attrs` property on [`Element`](#dia.Element.intro.presentation).</td>
<td>JointJS-style attributes applied on label's DOM element and its children. The same notation as the <code>attrs</code> property on <a href="#dia.Element.intro.presentation">Element</a>. Overridden by port group <code>attrs</code>, if provided.</td>
</tr>
</table>
</td>
</tr>
</table>
```javascript
label: {
position: {
Expand All @@ -154,47 +178,46 @@ label: {
#### Manual placement
It allows to set a label position directly.
It allows setting label position directly.
<table>
<tr>
<td><b>name</b></td>
<td><i>string</i></td>
<td>
`manual`
<code>'manual'</code>
</td>
</tr>
<tr>
<td><b>args</b></td>
<td><i>object | string</i></td>
<td><i>object</i></td>
<td>
<table>
<tr>
<td><b>x</b></td>
<td>number</td>
<td>Sets the label's `x` coordinate.</td>
<td>Sets the label's <code>x</code> coordinate.</td>
</tr>
<tr>
<td><b>y</b></td>
<td>number</td>
<td>Sets the label's `y` coordinate.</td>
<td>Sets the label's <code>y</code> coordinate.</td>
</tr>
<tr>
<td><b>angle</b></td>
<td>number</td>
<td>The port label rotation angle.</td>
<td>The port label rotation angle (in degrees in clockwise direction).</td>
</tr>
<tr>
<td><b>attrs</b></td>
<td>number</td>
<td>JointJS style attribute applied on label's DOM element and its children. The same notation as the `attrs` property on [`Element`](#dia.Element.intro.presentation).</td>
<td>object</td>
<td>JointJS-style attributes applied on label's DOM element and its children. The same notation as the <code>attrs</code> property on <a href="#dia.Element.intro.presentation">Element</a>. Overridden by port group <code>attrs</code>, if provided.</td>
</tr>
</table>
</td>
</tr>
</table>
```javascript
label: {
position: {
Expand All @@ -213,7 +236,3 @@ label: {
### Port label layout demo
<iframe src="about:blank" data-src="./demo/layout/PortLabel/portLabel.html" style="height: 442px; width: 803px;"></iframe>
61 changes: 28 additions & 33 deletions src/layout/ports/portLabel.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as util from '../../util/index.mjs';

function labelAttributes(opt1, opt2) {

// use value from `opt2` if it is missing in `opt1`
// use value from this object if it is missing in `opt2` as well
return util.defaultsDeep({}, opt1, opt2, {
x: 0,
y: 0,
Expand All @@ -11,22 +13,34 @@ function labelAttributes(opt1, opt2) {
});
}

function getBBoxAngles(elBBox) {

var center = elBBox.center();

var tl = center.theta(elBBox.origin());
var bl = center.theta(elBBox.bottomLeft());
var br = center.theta(elBBox.corner());
var tr = center.theta(elBBox.topRight());

return [tl, tr, br, bl];
}

function outsideLayout(portPosition, elBBox, autoOrient, opt) {

opt = util.defaults({}, opt, { offset: 15 });
var angle = elBBox.center().theta(portPosition);
var x = getBBoxAngles(elBBox);

var tx, ty, y, textAnchor;
var offset = opt.offset;
var orientAngle = 0;

if (angle < x[1] || angle > x[2]) {
const [topLeftAngle, bottomLeftAngle, bottomRightAngle, topRightAngle] = getBBoxAngles(elBBox);
if ((angle < bottomLeftAngle) || (angle > bottomRightAngle)) {
y = '.3em';
tx = offset;
ty = 0;
textAnchor = 'start';
} else if (angle < x[0]) {
} else if (angle < topLeftAngle) {
tx = 0;
ty = -offset;
if (autoOrient) {
Expand All @@ -37,7 +51,7 @@ function outsideLayout(portPosition, elBBox, autoOrient, opt) {
textAnchor = 'middle';
y = '0';
}
} else if (angle < x[3]) {
} else if (angle < topRightAngle) {
y = '.3em';
tx = -offset;
ty = 0;
Expand All @@ -56,43 +70,30 @@ function outsideLayout(portPosition, elBBox, autoOrient, opt) {
}

var round = Math.round;
return labelAttributes({
return labelAttributes(opt, {
x: round(tx),
y: round(ty),
angle: orientAngle,
attrs: { labelText: { y, textAnchor }}
});
}

function getBBoxAngles(elBBox) {

var center = elBBox.center();

var tl = center.theta(elBBox.origin());
var bl = center.theta(elBBox.bottomLeft());
var br = center.theta(elBBox.corner());
var tr = center.theta(elBBox.topRight());

return [tl, tr, br, bl];
}

function insideLayout(portPosition, elBBox, autoOrient, opt) {

var angle = elBBox.center().theta(portPosition);
opt = util.defaults({}, opt, { offset: 15 });
var angle = elBBox.center().theta(portPosition);

var tx, ty, y, textAnchor;
var offset = opt.offset;
var orientAngle = 0;

var bBoxAngles = getBBoxAngles(elBBox);

if (angle < bBoxAngles[1] || angle > bBoxAngles[2]) {
const [topLeftAngle, bottomLeftAngle, bottomRightAngle, topRightAngle] = getBBoxAngles(elBBox);
if ((angle < bottomLeftAngle) || (angle > bottomRightAngle)) {
y = '.3em';
tx = -offset;
ty = 0;
textAnchor = 'end';
} else if (angle < bBoxAngles[0]) {
} else if (angle < topLeftAngle) {
tx = 0;
ty = offset;
if (autoOrient) {
Expand All @@ -103,7 +104,7 @@ function insideLayout(portPosition, elBBox, autoOrient, opt) {
textAnchor = 'middle';
y = '.6em';
}
} else if (angle < bBoxAngles[3]) {
} else if (angle < topRightAngle) {
y = '.3em';
tx = offset;
ty = 0;
Expand All @@ -122,7 +123,7 @@ function insideLayout(portPosition, elBBox, autoOrient, opt) {
}

var round = Math.round;
return labelAttributes({
return labelAttributes(opt, {
x: round(tx),
y: round(ty),
angle: orientAngle,
Expand Down Expand Up @@ -158,16 +159,11 @@ function radialLayout(portCenterOffset, autoOrient, opt) {
}

var round = Math.round;
return labelAttributes({
return labelAttributes(opt, {
x: round(offset.x),
y: round(offset.y),
angle: autoOrient ? orientAngle : 0,
attrs: {
labelText: {
y,
textAnchor
}
}
angle: ((autoOrient) ? orientAngle : 0),
attrs: { labelText: { y, textAnchor }}
});
}

Expand Down Expand Up @@ -226,4 +222,3 @@ export const radial = function(portPosition, elBBox, opt) {
export const radialOriented = function(portPosition, elBBox, opt) {
return radialLayout(portPosition.difference(elBBox.center()), true, opt);
};

Loading

0 comments on commit 2b82631

Please sign in to comment.