Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/brave-labels-resolve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@joint/core": minor
---

dia.Link - add `getComputedLabel()`/`getComputedLabels()`, resolved against `defaultLabel`
63 changes: 55 additions & 8 deletions packages/joint-core/src/dia/Link.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Cell } from './Cell.mjs';
import { clone, isPlainObject, isFunction, isString, isNumber } from '../util/index.mjs';
import { clone, isPlainObject, isFunction, isString, isNumber, assign } from '../util/index.mjs';
import { Point, Polyline } from '../g/index.mjs';
import { getComputedLabel } from './link-labels.mjs';

// Link base model.
// --------------------------
Expand Down Expand Up @@ -55,7 +56,13 @@ export const Link = Cell.extend({
// used if neither defaultLabel.position
// nor label.position is set
position: {
distance: 0.5
distance: 0.5,
offset: 0,
angle: 0
},
size: {
width: 0,
height: 0
}
}
},
Expand Down Expand Up @@ -216,6 +223,31 @@ export const Link = Cell.extend({
return this.prop(['labels', idx], label, opt);
},

/**
* Returns the label at the given index, resolved against the link's `defaultLabel`
* and the built-in default label.
*
* Unlike the `label()` getter, which returns the label exactly as stored, the result
* has `markup`, `attrs`, `size` and `position` merged with the defaults.
* The stored label is not modified.
*
* @param {number} [idx=0] - The index of the label. Negative values count from the end.
* @returns {dia.Link.ComputedLabel | null} A new object with the resolved label, or `null`
* if there is no label at `idx`.
*/
getComputedLabel: function(idx) {

const labels = this.labels();

let index = (isFinite(idx) && idx !== null) ? (idx | 0) : 0;
if (index < 0) {
index = labels.length + index;
}

const label = labels[index];
return (label === undefined) ? null : getComputedLabel(this, label);
},

labels: function(labels, opt) {

// getter
Expand All @@ -229,6 +261,22 @@ export const Link = Cell.extend({
return this.set('labels', labels, opt);
},

/**
* Returns all labels of the link, each resolved against the link's `defaultLabel`
* and the built-in default label.
*
* Unlike the `labels()` getter, which returns the labels exactly as stored, each
* has `markup`, `attrs`, `size` and `position` merged with the defaults.
* The stored labels are not modified.
*
* @returns {dia.Link.ComputedLabel[]} A new array of resolved labels, in the same order as
* `labels()`. Empty if the link has no labels.
*/
getComputedLabels: function() {

return this.labels().map((label) => getComputedLabel(this, label));
},

hasLabels: function() {
const { labels } = this.attributes;
return Array.isArray(labels) && labels.length > 0;
Expand Down Expand Up @@ -541,16 +589,15 @@ export const Link = Cell.extend({
return !!ancestor && (ancestor.id === cellId || ancestor.isEmbeddedIn(cellId));
},

// Get resolved default label.
// Get resolved default label. Kept as-is (including any custom property, e.g. a
// `@joint/layout-elk` `elkLayoutOptions`) - not just the known `markup`/`attrs`/
// `size`/`position` - so `getComputedLabel` (`link-labels.mjs`) can pass it through too.
_getDefaultLabel: function() {

var defaultLabel = this.get('defaultLabel') || this.defaultLabel || {};
const defaultLabel = this.get('defaultLabel') || this.defaultLabel || {};

var label = {};
const label = assign({}, defaultLabel);
label.markup = defaultLabel.markup || this.get('labelMarkup') || this.labelMarkup;
label.position = defaultLabel.position;
label.attrs = defaultLabel.attrs;
label.size = defaultLabel.size;

return label;
}
Expand Down
Loading
Loading