maxGraph/packages/html/stories/AutoLayout.stories.js

217 lines
5.4 KiB
JavaScript
Raw Normal View History

import mxgraph from '@mxgraph/core';
import { globalTypes } from '../.storybook/preview';
export default {
title: 'Layouts/AutoLayout',
argTypes: {
...globalTypes,
contextMenu: {
type: 'boolean',
defaultValue: false
},
rubberBand: {
type: 'boolean',
defaultValue: true
}
}
};
const Template = ({ label, ...args }) => {
const {
mxGraph,
mxRubberband,
mxEvent,
mxUtils,
mxCellRenderer,
mxEdgeHandler,
mxHierarchicalLayout,
mxConstants,
mxCellOverlay,
mxImage,
mxClient,
mxMorphing,
mxEventObject,
mxEventUtils
} = mxgraph;
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';
if (!args.contextMenu)
mxEvent.disableContextMenu(container);
class MyCustomCellRenderer extends mxCellRenderer {
installCellOverlayListeners(state, overlay, shape) {
super.installCellOverlayListeners(state, overlay, shape);
mxEvent.addListener(
shape.node,
mxClient.IS_POINTER ? 'pointerdown' : 'mousedown',
evt => {
overlay.fireEvent(
new mxEventObject('pointerdown', 'event', evt, 'state', state)
);
}
);
if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {
mxEvent.addListener(shape.node, 'touchstart', evt => {
overlay.fireEvent(
new mxEventObject('pointerdown', 'event', evt, 'state', state)
);
});
}
}
}
class MyCustomEdgeHandler extends mxEdgeHandler {
connect(edge, terminal, isSource, isClone, me) {
super.connect(edge, terminal, isSource, isClone, me);
executeLayout();
}
}
class MyCustomGraph extends mxGraph {
createEdgeHandler(state, edgeStyle) {
return new MyCustomEdgeHandler(state, edgeStyle);
}
createCellRenderer() {
return new MyCustomCellRenderer();
}
}
// Creates the graph inside the given this.el
const graph = new MyCustomGraph(container);
graph.setPanning(true);
graph.panningHandler.useLeftButtonForPanning = true;
graph.setAllowDanglingEdges(false);
graph.connectionHandler.select = false;
graph.view.setTranslate(20, 20);
// Enables rubberband selection
if (args.rubberBand)
new mxRubberband(graph);
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
const parent = graph.getDefaultParent();
const layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);
const executeLayout = (change, post) => {
graph.getModel().beginUpdate();
try {
if (change != null) {
change();
}
layout.execute(graph.getDefaultParent(), v1);
} catch (e) {
throw e;
} finally {
// New API for animating graph layout results asynchronously
const morph = new mxMorphing(graph);
morph.addListener(mxEvent.DONE, () => {
graph.getModel().endUpdate();
if (post != null) {
post();
}
});
morph.startAnimation();
}
};
const addOverlay = cell => {
// Creates a new overlay with an image and a tooltip
const overlay = new mxCellOverlay(
new mxImage('images/add.png', 24, 24),
'Add outgoing'
);
overlay.cursor = 'hand';
// Installs a handler for clicks on the overlay
overlay.addListener(mxEvent.CLICK, (sender, evt2) => {
graph.clearSelection();
const geo = graph.getCellGeometry(cell);
let v2;
executeLayout(
() => {
v2 = graph.insertVertex({
parent,
value: 'World!',
position: [geo.x, geo.y],
size: [80, 30],
});
addOverlay(v2);
graph.view.refresh(v2);
const e1 = graph.insertEdge({
parent,
source: cell,
target: v2,
});
},
() => {
graph.scrollCellToVisible(v2);
}
);
});
// Special CMS event
overlay.addListener('pointerdown', (sender, eo) => {
const evt2 = eo.getProperty('event');
const state = eo.getProperty('state');
graph.popupMenuHandler.hideMenu();
graph.stopEditing(false);
const pt = mxUtils.convertPoint(
graph.container,
mxEventUtils.getClientX(evt2),
mxEventUtils.getClientY(evt2)
);
graph.connectionHandler.start(state, pt.x, pt.y);
graph.isMouseDown = true;
graph.isMouseTrigger = mxEventUtils.isMouseEvent(evt2);
mxEvent.consume(evt2);
});
// Sets the overlay for the cell in the graph
graph.addCellOverlay(cell, overlay);
};
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
let v1;
try {
v1 = graph.insertVertex({
parent,
value: 'Hello,',
position: [0, 0],
size: [80, 30],
});
addOverlay(v1);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
graph.resizeCell = function() {
mxGraph.prototype.resizeCell.apply(this, arguments);
executeLayout();
};
graph.connectionHandler.addListener(mxEvent.CONNECT, function() {
executeLayout();
});
return container;
}
export const Default = Template.bind({});