maxGraph/packages/html/stories/SecondLabel.stories.js

235 lines
6.6 KiB
JavaScript
Raw Normal View History

import mxgraph from '@mxgraph/core';
import { globalTypes } from '../.storybook/preview';
export default {
title: 'Labels/SecondLabel',
argTypes: {
...globalTypes
}
};
const Template = ({ label, ...args }) => {
const {
mxGraph,
mxRectangleShape,
mxDomHelpers,
mxText,
mxPoint,
mxRectangle,
mxConstants
} = mxgraph;
const div = document.createElement('div');
const container = document.createElement('div');
container.style.position = 'relative';
container.style.overflow = 'hidden';
container.style.width = `${args.width}px`;
container.style.height = `${args.height}px`;
container.style.background = 'url(/images/grid.gif)';
container.style.cursor = 'default';
div.appendChild(container);
// Simple solution to add additional text to the rectangle shape definition:
(function() {
const mxRectangleShapeIsHtmlAllowed =
mxRectangleShape.prototype.isHtmlAllowed;
mxRectangleShape.prototype.isHtmlAllowed = function() {
return (
mxRectangleShapeIsHtmlAllowed.apply(this, arguments) &&
this.state == null
);
};
const mxRectangleShapePaintForeground =
mxRectangleShape.prototype.paintForeground;
mxRectangleShape.prototype.paintForeground = function(c, x, y, w, h) {
if (
this.state != null &&
this.state.cell.geometry != null &&
!this.state.cell.geometry.relative
) {
c.setFontColor('#a0a0a0');
c.text(x + 2, y, 0, 0, this.state.cell.id, 'left', 'top');
}
mxRectangleShapePaintForeground.apply(this, arguments);
};
})();
// Creates the graph inside the given container
const graph = new mxGraph(container);
// Disables the folding icon
graph.isCellFoldable = function(cell) {
return false;
};
let secondLabelVisible = true;
// Hook for returning shape number for a given cell
graph.getSecondLabel = function(cell) {
if (!cell.isEdge()) {
// Possible to return any string here
return `The ID of this cell is ${cell.id}`;
}
return null;
};
let relativeChildVerticesVisible = true;
// Overrides method to hide relative child vertices
// TODO this function is not used
const isVisible = function() {
return (
!cell.isVertex() ||
cell.geometry == null ||
!cell.geometry.relative ||
cell.geometry.relative == relativeChildVerticesVisible
);
};
// Creates the shape for the shape number and puts it into the draw pane
const { redrawShape } = graph.cellRenderer;
graph.cellRenderer.redrawShape = function(state, force, rendering) {
const result = redrawShape.apply(this, arguments);
if (
result &&
secondLabelVisible &&
state.cell.geometry != null &&
!state.cell.geometry.relative
) {
const secondLabel = graph.getSecondLabel(state.cell);
if (
secondLabel != null &&
state.shape != null &&
state.secondLabel == null
) {
state.secondLabel = new mxText(
secondLabel,
new mxRectangle(),
mxConstants.ALIGN_LEFT,
mxConstants.ALIGN_BOTTOM
);
// Styles the label
state.secondLabel.color = 'black';
state.secondLabel.family = 'Verdana';
state.secondLabel.size = 8;
state.secondLabel.fontStyle = mxConstants.FONT_ITALIC;
state.secondLabel.background = 'yellow';
state.secondLabel.border = 'black';
state.secondLabel.valign = 'bottom';
state.secondLabel.dialect = state.shape.dialect;
state.secondLabel.dialect = mxConstants.DIALECT_STRICTHTML;
state.secondLabel.wrap = true;
graph.cellRenderer.initializeLabel(state, state.secondLabel);
}
}
if (state.secondLabel != null) {
const scale = graph.getView().getScale();
const bounds = new mxRectangle(
state.x + state.width - 8 * scale,
state.y + 8 * scale,
35,
0
);
state.secondLabel.state = state;
state.secondLabel.value = graph.getSecondLabel(state.cell);
state.secondLabel.scale = scale;
state.secondLabel.bounds = bounds;
state.secondLabel.redraw();
}
return result;
};
// Destroys the shape number
const { destroy } = graph.cellRenderer;
graph.cellRenderer.destroy = function(state) {
destroy.apply(this, arguments);
if (state.secondLabel != null) {
state.secondLabel.destroy();
state.secondLabel = null;
}
};
graph.cellRenderer.getShapesForState = function(state) {
return [state.shape, state.text, state.secondLabel, state.control];
};
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
const parent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try {
const v1 = graph.insertVertex(parent, null, 'Hello,', 30, 40, 80, 30);
// Alternative solution of creating a second label by creating a realtive child vertex
// with size (0, 0). This will not be selectable and only the label colors can be used
// for coloring as the actual shape will have zero size.
const v11 = graph.insertVertex(
v1,
null,
'World',
1,
1,
0,
0,
'align=left;verticalAlign=top;labelBackgroundColor=red;labelBorderColor=black',
true
);
v11.geometry.offset = new mxPoint(-8, -8);
const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
// Another alternative solution of creating a second label as a relative child vertex
// but this time with an automatic size so that the cell is actually selectable and
// the background is painted as a shape.
const v21 = graph.insertVertex(
v2,
null,
'World',
1,
1,
0,
0,
'align=left;verticalAlign=top;fillColor=red;rounded=1;spacingLeft=4;spacingRight=4',
true
);
v21.geometry.offset = new mxPoint(-8, -8);
graph.updateCellSize(v21);
const e1 = graph.insertEdge(parent, null, '', v1, v2);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
const buttons = document.createElement('div');
div.appendChild(buttons);
// Adds a button to execute the layout
buttons.appendChild(
mxDomHelpers.button('Toggle Child Vertices', function(evt) {
relativeChildVerticesVisible = !relativeChildVerticesVisible;
graph.refresh();
})
);
// Adds a button to execute the layout
buttons.appendChild(
mxDomHelpers.button('Toggle IDs', function(evt) {
secondLabelVisible = !secondLabelVisible;
graph.refresh();
})
);
return div;
}
export const Default = Template.bind({});