diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json index 09d03509fd..39fce3b3a8 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@lerna/filter-options": "^4.0.0", "babel-loader": "^8.2.3", "better-docs": "^2.3.2", + "cross-env": "^7.0.3", "css-loader": "^6.5.1", "file-loader": "^6.2.0", "jsdoc": "^3.6.7", @@ -46,4 +47,5 @@ "webpack-merge": "^5.8.0" }, "sideEffects": true + } diff --git a/packages/core/css/common.css b/packages/core/css/common.css index f7eb430aed..78aef68b3b 100644 --- a/packages/core/css/common.css +++ b/packages/core/css/common.css @@ -42,7 +42,7 @@ table.MaxWindow { font-family: Arial; font-size: 8pt; } -td.mxWindowTitle { +td.MaxWindowTitle { background: url(data:image/gif;base64,R0lGODlhFwAXAMQAANfX18rKyuHh4c7OzsDAwMHBwc/Pz+Li4uTk5NHR0dvb2+jo6O/v79/f3/n5+dnZ2dbW1uPj44yMjNPT0+Dg4N3d3ebm5szMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAXABcAAAWQICESxWiW5Ck6bOu+MMvMdG3f86LvfO/rlqBwSCwaj8ikUohoOp/QaDNCrVqvWKpgezhsv+AwmEIum89ocmPNbrvf64p8Tq/b5Yq8fs/v5x+AgYKDhIAAh4iJiouHEI6PkJGSjhOVlpeYmZUJnJ2en6CcBqMDpaanqKgXq6ytrq+rAbKztLW2shK5uru8vbkhADs=) repeat-x; _background: url('../images/window-title.gif') repeat-x; text-overflow: ellipsis; @@ -56,19 +56,19 @@ td.mxWindowTitle { padding-bottom: 6px; color: black; } -td.mxWindowPane { +td.MaxWindowPane { vertical-align: top; padding: 0px; } -div.mxWindowPane { +div.MaxWindowPane { overflow: hidden; position: relative; } -td.mxWindowPane td { +td.MaxWindowPane td { font-family: Arial; font-size: 8pt; } -td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio { +td.MaxWindowPane input, td.MaxWindowPane select, td.MaxWindowPane textarea, td.MaxWindowPane radio { border-color: #8C8C8C; border-style: solid; border-width: 1px; @@ -76,7 +76,7 @@ td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWi font-size: 8pt; padding: 1px; } -td.mxWindowPane button { +td.MaxWindowPane button { background: url(data:image/gif;base64,R0lGODlhCgATALMAAP7+/t7e3vj4+Ojo6OXl5e/v7/n5+fb29vPz8/39/e3t7fHx8e7u7v///wAAAAAAACH5BAAAAAAALAAAAAAKABMAAAQ2MMlJhb0Y6c2X/2AhjiRjnqiirizqMkEsz0Rt30Ou7y8K/ouDcEg0GI9IgHLJbDif0Kh06owAADs=) repeat-x; _background: url('../images/button.gif') repeat-x; font-family: Arial; diff --git a/packages/core/images/check.png b/packages/core/images/check.png new file mode 100644 index 0000000000..3f3110a14f Binary files /dev/null and b/packages/core/images/check.png differ diff --git a/packages/core/images/connector.gif b/packages/core/images/connector.gif new file mode 100644 index 0000000000..326e061ea8 Binary files /dev/null and b/packages/core/images/connector.gif differ diff --git a/packages/core/images/dot.gif b/packages/core/images/dot.gif new file mode 100644 index 0000000000..08b9947649 Binary files /dev/null and b/packages/core/images/dot.gif differ diff --git a/packages/core/images/error.png b/packages/core/images/error.png new file mode 100644 index 0000000000..eb1491b416 Binary files /dev/null and b/packages/core/images/error.png differ diff --git a/packages/core/images/fit_to_size.png b/packages/core/images/fit_to_size.png new file mode 100644 index 0000000000..4de46b015f Binary files /dev/null and b/packages/core/images/fit_to_size.png differ diff --git a/packages/core/images/flash.png b/packages/core/images/flash.png new file mode 100644 index 0000000000..aa6fd2d1e9 Binary files /dev/null and b/packages/core/images/flash.png differ diff --git a/packages/core/images/forbidden.png b/packages/core/images/forbidden.png new file mode 100644 index 0000000000..04d5f4ab19 Binary files /dev/null and b/packages/core/images/forbidden.png differ diff --git a/packages/core/images/help.png b/packages/core/images/help.png new file mode 100644 index 0000000000..e8ceddb370 Binary files /dev/null and b/packages/core/images/help.png differ diff --git a/packages/core/images/house.png b/packages/core/images/house.png new file mode 100644 index 0000000000..c652bc8dae Binary files /dev/null and b/packages/core/images/house.png differ diff --git a/packages/core/images/information.png b/packages/core/images/information.png new file mode 100644 index 0000000000..5df1857444 Binary files /dev/null and b/packages/core/images/information.png differ diff --git a/packages/core/images/lightbulb_on.png b/packages/core/images/lightbulb_on.png new file mode 100644 index 0000000000..8b594120dd Binary files /dev/null and b/packages/core/images/lightbulb_on.png differ diff --git a/packages/core/images/pencil.png b/packages/core/images/pencil.png new file mode 100644 index 0000000000..712443eb68 Binary files /dev/null and b/packages/core/images/pencil.png differ diff --git a/packages/core/images/plus.png b/packages/core/images/plus.png new file mode 100644 index 0000000000..24a84bb492 Binary files /dev/null and b/packages/core/images/plus.png differ diff --git a/packages/core/images/printer.png b/packages/core/images/printer.png new file mode 100644 index 0000000000..6004816bc6 Binary files /dev/null and b/packages/core/images/printer.png differ diff --git a/packages/core/images/users3.png b/packages/core/images/users3.png new file mode 100644 index 0000000000..2185bf46ca Binary files /dev/null and b/packages/core/images/users3.png differ diff --git a/packages/core/images/workplace.png b/packages/core/images/workplace.png new file mode 100644 index 0000000000..2a0bedd553 Binary files /dev/null and b/packages/core/images/workplace.png differ diff --git a/packages/core/src/gui/MaxWindow.ts b/packages/core/src/gui/MaxWindow.ts index e25fd30814..592738f7a3 100644 --- a/packages/core/src/gui/MaxWindow.ts +++ b/packages/core/src/gui/MaxWindow.ts @@ -177,7 +177,7 @@ class MaxWindow extends EventSource { minimizable: boolean=true, movable: boolean=true, replaceNode: HTMLElement | null=null, - style: string='' + style: string | undefined =undefined ) { super(); diff --git a/packages/core/src/serialization/Codec.ts b/packages/core/src/serialization/Codec.ts index 12937af5fc..e921c52e1c 100644 --- a/packages/core/src/serialization/Codec.ts +++ b/packages/core/src/serialization/Codec.ts @@ -13,6 +13,9 @@ import MaxLog from '../gui/MaxLog'; import { getFunctionName } from '../util/StringUtils'; import { importNode, isNode } from '../util/domUtils'; import ObjectCodec from './ObjectCodec'; +import GraphDataModel from '../view/GraphDataModel'; +import Geometry from '../view/geometry/Geometry'; +import Point from '../view/geometry/Point'; const createXmlDocument = () => { return document.implementation.createDocument('', '', null); @@ -339,6 +342,20 @@ class Codec { * @param into Optional object to be decodec into. */ decode(node: Element, into?: any): any { + + + //****Edit note - there may be other classes needed here????****** + const classMap = { + "GraphDataModel": GraphDataModel, + "Geometry": Geometry, + "Point":Point, + "Array": Array, + "Object": Object, + "Boolean": Boolean, + + + + }; this.updateElements(); let obj = null; @@ -347,11 +364,11 @@ class Codec { try { // @ts-ignore - ctor = window[node.nodeName]; + ctor = classMap[node.nodeName] + if (ctor == undefined) console.log(node.nodeName) } catch (err) { - // ignore + console.log(err)// ignore } - const dec = CodecRegistry.getCodec(ctor); if (dec != null) { diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 99427259c9..dfee9ae0a5 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -82,6 +82,7 @@ export type CellStateStyle = { imageBorder?: ColorValue; imageHeight?: number; imageWidth?: number; + imageVerticalAlign?: VAlignValue; indicatorColor?: ColorValue; indicatorDirection?: DirectionValue; indicatorHeight?: number; diff --git a/packages/core/src/util/Utils.ts b/packages/core/src/util/Utils.ts index 2f852271fb..2898c5b661 100644 --- a/packages/core/src/util/Utils.ts +++ b/packages/core/src/util/Utils.ts @@ -60,6 +60,22 @@ export const mixInto = (dest: any) => (mixin: any) => { } }; +//getBBox of SVG element before rendered in DOM + +export function svgBBox (svgEl: SVGGElement){ + let tempDiv = document.createElement('div') + tempDiv.setAttribute('style', "position:absolute; visibility:hidden; width:0, height:0") + document.body.appendChild(tempDiv) + let tempSvg = document.createElementNS("http://www.w3.org/2000/svg", 'svg') + tempDiv.appendChild(tempSvg) + let tempEl = svgEl.cloneNode(true) + tempSvg.appendChild(tempEl) + let bb = (tempEl).getBBox() + document.body.removeChild(tempDiv) + return bb + +} + /** * Returns the value for the given key in the given associative array or * the given default value if the value is null. diff --git a/packages/core/src/util/cloneUtils.ts b/packages/core/src/util/cloneUtils.ts index 9a26e10fe0..85a72aaf79 100644 --- a/packages/core/src/util/cloneUtils.ts +++ b/packages/core/src/util/cloneUtils.ts @@ -25,11 +25,11 @@ export const clone = function _clone(obj: any, transients: string[] | null=null, i != ObjectIdentity.FIELD_NAME && (transients == null || transients.indexOf(i) < 0) ) { - if (!shallow && typeof obj[i] === 'object') { + if (!shallow && typeof obj[i] === 'object') { clone[i] = _clone(obj[i]); } else { clone[i] = obj[i]; - } + } } } } diff --git a/packages/core/src/util/styleUtils.ts b/packages/core/src/util/styleUtils.ts index 3f930f4518..edeeef9eac 100644 --- a/packages/core/src/util/styleUtils.ts +++ b/packages/core/src/util/styleUtils.ts @@ -19,8 +19,10 @@ import Rectangle from '../view/geometry/Rectangle'; import Cell from '../view/cell/Cell'; import GraphDataModel from '../view/GraphDataModel'; import CellArray from '../view/cell/CellArray'; +import {clone} from './cloneUtils' import { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from 'src/types'; + /** * Removes the cursors from the style of the given DOM node and its * descendants. @@ -438,9 +440,10 @@ export const setCellStyles = ( if (cell) { const style = cell.getStyle(); - style[key] = value; + const styleClone =clone(style) + styleClone[key] = value; - model.setStyle(cell, style); + model.setStyle(cell, styleClone); } } } finally { @@ -490,6 +493,7 @@ export const setStyle = (style: string | null, key: string, value: any) => { next < 0 ? ';' : style.substring(next) }`; } else { + style = style.substring(0, index) + (next < 0 ? ';' : style.substring(next)); } } diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts index f92c1473da..ef829348b4 100644 --- a/packages/core/src/view/Graph.ts +++ b/packages/core/src/view/Graph.ts @@ -580,10 +580,8 @@ class Graph extends EventSource { const newParent = change.child.getParent(); this.view.invalidate(change.child, true, true); - if ( - newParent && - (!this.getDataModel().contains(newParent) || newParent.isCollapsed()) - ) { + if (newParent == null || !this.getDataModel().contains(newParent) || newParent.isCollapsed()) + { this.view.invalidate(change.child, true, true); this.removeStateForCell(change.child); @@ -1370,7 +1368,7 @@ class Graph extends EventSource { setAllowLoops(value: boolean) { this.allowLoops = value; } - + /** * Returns {@link recursiveResize}. * diff --git a/packages/core/src/view/GraphDataModel.ts b/packages/core/src/view/GraphDataModel.ts index 427ebae4f4..1f054e0d91 100644 --- a/packages/core/src/view/GraphDataModel.ts +++ b/packages/core/src/view/GraphDataModel.ts @@ -389,7 +389,7 @@ export class GraphDataModel extends EventSource { * @param {Cell} cell that represents the possible layer. */ isLayer(cell: Cell) { - return this.isRoot(cell.getParent()); + return cell != null && this.isRoot(cell.getParent()); } /** diff --git a/packages/core/src/view/GraphView.ts b/packages/core/src/view/GraphView.ts index 4d81838dd6..323dcab79b 100644 --- a/packages/core/src/view/GraphView.ts +++ b/packages/core/src/view/GraphView.ts @@ -801,7 +801,7 @@ export class GraphView extends EventSource { if (cell) { state = this.getState(cell); - + if (state) { if (state.invalid) { state.invalid = false; @@ -857,14 +857,14 @@ export class GraphView extends EventSource { * @param state {@link CellState} to be updated. */ updateCellState(state: CellState) { - const absoluteOffset = state.absoluteOffset; - const origin = state.origin; + const absoluteOffset = state.absoluteOffset; + const origin = state.origin; - absoluteOffset.x = 0; - absoluteOffset.y = 0; - origin.x = 0; - origin.y = 0; - state.length = 0; + absoluteOffset.x = 0; + absoluteOffset.y = 0; + origin.x = 0; + origin.y = 0; + state.length = 0; if (state.cell !== this.currentRoot) { const parent = state.cell.getParent(); @@ -890,11 +890,11 @@ export class GraphView extends EventSource { if (geo.relative && pState) { if (pState.cell.isEdge()) { - const origin = this.getPoint(pState, geo); + const originP = this.getPoint(pState, geo); - if (origin) { - origin.x += origin.x / this.scale - pState.origin.x - this.translate.x; - origin.y += origin.y / this.scale - pState.origin.y - this.translate.y; + if (originP) { + origin.x += (originP.x / this.scale) - pState.origin.x - this.translate.x; + origin.y += (originP.y / this.scale) - pState.origin.y - this.translate.y; } } else { origin.x += geo.x * pState.unscaledWidth + offset.x; @@ -1216,7 +1216,7 @@ export class GraphView extends EventSource { pts.push((edge.absolutePoints)[0]); const edgeStyle = this.getEdgeStyle(edge, points, source, target); - if (edgeStyle && source) { + if (edgeStyle) { // target can be null const src = this.getTerminalPort(edge, source, true); const trg = target ? this.getTerminalPort(edge, target, false) : null; @@ -1387,7 +1387,7 @@ export class GraphView extends EventSource { */ getFloatingTerminalPoint( edge: CellState, - start: CellState, + start: CellState| null, end: CellState | null, source: boolean ) { @@ -1395,8 +1395,8 @@ export class GraphView extends EventSource { let next = this.getNextPoint(edge, end, source); const orth = this.graph.isOrthogonal(edge); - const alpha = toRadians(start.style.rotation ?? 0); - const center = new Point(start.getCenterX(), start.getCenterY()); + const alpha = toRadians(start?.style.rotation ?? 0); + const center = new Point(start?.getCenterX(), start?.getCenterY()); if (alpha !== 0) { const cos = Math.cos(-alpha); @@ -1427,7 +1427,7 @@ export class GraphView extends EventSource { * @param terminal {@link CellState} that represents the terminal. * @param source Boolean indicating if the given terminal is the source terminal. */ - getTerminalPort(state: CellState, terminal: CellState, source: boolean = false) { + getTerminalPort(state: CellState, terminal: CellState|null, source: boolean = false) { const key = source ? 'sourcePort' : 'targetPort'; const id = state.style[key]; @@ -1460,7 +1460,7 @@ export class GraphView extends EventSource { * @param border Optional border between the perimeter and the shape. */ getPerimeterPoint( - terminal: CellState, + terminal: CellState|null, next: Point, orthogonal: boolean, border = 0 @@ -2193,7 +2193,7 @@ export class GraphView extends EventSource { } }; - this.endHandler = (evt: MouseEvent) => { + this.endHandler = (evt: MouseEvent) => { if ( this.captureDocumentGesture && graph.isMouseDown && diff --git a/packages/core/src/view/canvas/SvgCanvas2D.ts b/packages/core/src/view/canvas/SvgCanvas2D.ts index 9619e8cf74..9515bd0da3 100644 --- a/packages/core/src/view/canvas/SvgCanvas2D.ts +++ b/packages/core/src/view/canvas/SvgCanvas2D.ts @@ -994,9 +994,10 @@ class SvgCanvas2D extends AbstractCanvas2D { * Private helper function to create SVG elements */ roundrect(x: number, y: number, w: number, h: number, dx: number, dy: number) { - if (!this.node) return; + + this.rect(x, y, w, h); //creates this.node - this.rect(x, y, w, h); + if(!this.node)return if (dx > 0) { this.node.setAttribute('rx', String(this.format(dx * this.state.scale))); @@ -1559,7 +1560,7 @@ class SvgCanvas2D extends AbstractCanvas2D { tr += `rotate(${rotation},${this.format(x * s.scale)},${this.format(y * s.scale)})`; } - if (dir != null) { + if (dir != '') { node.setAttribute('direction', dir); } @@ -1819,9 +1820,9 @@ class SvgCanvas2D extends AbstractCanvas2D { } bbox = new Rectangle( - (x + 1) * s.scale, + x * s.scale, (y + 2) * s.scale, - w * s.scale, + (w +1) * s.scale, (h + 1) * s.scale ); } @@ -1835,7 +1836,7 @@ class SvgCanvas2D extends AbstractCanvas2D { n.setAttribute('width', String(Math.ceil(bbox.width + 2))); n.setAttribute('height', String(Math.ceil(bbox.height))); - const sw = s.fontBorderColor ? Math.max(1, this.format(s.scale)) : 0; + const sw = s.fontBorderColor !== 'none' ? Math.max(1, this.format(s.scale)) : 0; n.setAttribute('stroke-width', String(sw)); // Workaround for crisp rendering - only required if not exporting diff --git a/packages/core/src/view/cell/TemporaryCellStates.ts b/packages/core/src/view/cell/TemporaryCellStates.ts index 51f5a28efb..4e29b90f11 100644 --- a/packages/core/src/view/cell/TemporaryCellStates.ts +++ b/packages/core/src/view/cell/TemporaryCellStates.ts @@ -57,11 +57,11 @@ class TemporaryCellStates { // Overrides doRedrawShape and paint shape to add links on shapes if (getLinkForCellState != null) { - (view.graph).cellRenderer.doRedrawShape = (state: CellState) => { + (view.graph).cellRenderer.doRedrawShape = function(state: CellState) { const shape = state?.shape; const oldPaint = shape.paint; - shape.paint = (c) => { + shape.paint = function (c) { const link = getLinkForCellState(state); if (link != null) { c.setLink(link); @@ -80,7 +80,7 @@ class TemporaryCellStates { // Overrides validateCellState to ignore invisible cells view.validateCellState = (cell, recurse) => { if (cell == null || isCellVisibleFn == null || isCellVisibleFn(cell)) { - return (self.oldDoRedrawShape).apply(view, [cell, recurse]); + return (self.oldValidateCellState).apply(view, [cell, recurse]); } return null; }; diff --git a/packages/core/src/view/geometry/edge/ConnectorShape.ts b/packages/core/src/view/geometry/edge/ConnectorShape.ts index d34bbd3579..5f11c6ad99 100644 --- a/packages/core/src/view/geometry/edge/ConnectorShape.ts +++ b/packages/core/src/view/geometry/edge/ConnectorShape.ts @@ -100,7 +100,7 @@ class ConnectorShape extends PolylineShape { // Allow for stroke width in the end point used and the // orthogonal vectors describing the direction of the marker - const filled = !(source ? this.style.startFill : this.style.endFill); + const filled = Boolean(source ? this.style.startFill : this.style.endFill); result = MarkerShape.createMarker( c, diff --git a/packages/core/src/view/geometry/node/LabelShape.ts b/packages/core/src/view/geometry/node/LabelShape.ts index 79c930fc2f..0df5e6ad70 100644 --- a/packages/core/src/view/geometry/node/LabelShape.ts +++ b/packages/core/src/view/geometry/node/LabelShape.ts @@ -154,7 +154,7 @@ class LabelShape extends RectangleShape { */ getImageBounds(x: number, y: number, w: number, h: number) { const align = this.style?.imageAlign ?? ALIGN.LEFT; - const valign = this.style?.verticalAlign ?? ALIGN.MIDDLE; + const valign = this.style?.imageVerticalAlign ?? ALIGN.MIDDLE; const width = this.style?.imageWidth ?? DEFAULT_IMAGESIZE; const height = this.style?.imageHeight ?? DEFAULT_IMAGESIZE; const spacing = this.style?.spacing ?? this.spacing + 5; @@ -217,7 +217,7 @@ class LabelShape extends RectangleShape { */ getIndicatorBounds(x: number, y: number, w: number, h: number) { const align = this.style?.imageAlign ?? ALIGN.LEFT; - const valign = this.style?.verticalAlign ?? ALIGN.MIDDLE; + const valign = this.style?.imageVerticalAlign ?? ALIGN.MIDDLE; const width = this.style?.indicatorWidth ?? this.indicatorSize; const height = this.style?.indicatorHeight ?? this.indicatorSize; const spacing = this.spacing + 5; diff --git a/packages/core/src/view/geometry/node/TextShape.ts b/packages/core/src/view/geometry/node/TextShape.ts index e82d0643e2..634e4ea092 100644 --- a/packages/core/src/view/geometry/node/TextShape.ts +++ b/packages/core/src/view/geometry/node/TextShape.ts @@ -32,6 +32,7 @@ import { replaceTrailingNewlines, trim, } from '../../../util/StringUtils'; +import {svgBBox} from '../../../util/Utils'; import { isNode } from '../../../util/domUtils'; import { AlignValue, @@ -373,10 +374,9 @@ class TextShape extends Shape { (this.style.spacingRight ?? this.spacingRight - old) + this.spacing; this.spacingBottom = (this.style.spacingBottom ?? this.spacingBottom - old) + this.spacing; - this.spacingLeft = - (this.style.spacingLeft ?? this.spacingLeft - old) + this.spacing; + this.spacingLeft = (this.style.spacingLeft ?? this.spacingLeft - old) + this.spacing; this.horizontal = this.style.horizontal ?? this.horizontal; - this.background = this.style.backgroundColor ?? this.background; + this.background = this.style.labelBackgroundColor ?? this.background; this.border = this.style.labelBorderColor ?? this.border; this.textDirection = this.style.textDirection ?? DEFAULT_TEXT_DIRECTION; this.opacity = this.style.textOpacity ?? 100; @@ -470,12 +470,13 @@ class TextShape extends Shape { } else { try { const b = node.getBBox(); - + // Workaround for bounding box of empty string if (typeof this.value === 'string' && trim(this.value)?.length === 0) { this.boundingBox = null; } else if (b.width === 0 && b.height === 0) { - this.boundingBox = null; + const box = svgBBox(node); + this.boundingBox = new Rectangle(box.x, box.y, box.width, box.height); } else { this.boundingBox = new Rectangle(b.x, b.y, b.width, b.height); } diff --git a/packages/core/src/view/handler/CellEditorHandler.ts b/packages/core/src/view/handler/CellEditorHandler.ts index 2a0d86baae..0ddde5f8a7 100644 --- a/packages/core/src/view/handler/CellEditorHandler.ts +++ b/packages/core/src/view/handler/CellEditorHandler.ts @@ -305,7 +305,7 @@ class CellEditorHandler implements GraphPlugin { this.textarea.style.minHeight = '1em'; } - this.textarea.style.position = 'relative'; + this.textarea.style.position = 'absolute'; this.installListeners(this.textarea); } @@ -791,7 +791,7 @@ class CellEditorHandler implements GraphPlugin { if ( this.autoSize && // @ts-ignore - (this.graph.model.isEdge(state.cell) || state.style.overflow !== 'fill') + (state.cell.isEdge() || state.style.overflow !== 'fill') ) { window.setTimeout(() => { this.resize(); @@ -854,7 +854,6 @@ class CellEditorHandler implements GraphPlugin { const initial = this.initialValue; this.initialValue = null; this.editingCell = null; - this.trigger = null; this.bounds = null; textarea.blur(); clearSelection(); @@ -888,6 +887,7 @@ class CellEditorHandler implements GraphPlugin { this.textarea = null; this.align = null; + this.trigger = null; } } diff --git a/packages/core/src/view/handler/EdgeHandler.ts b/packages/core/src/view/handler/EdgeHandler.ts index bb3fd58535..247d96bbef 100644 --- a/packages/core/src/view/handler/EdgeHandler.ts +++ b/packages/core/src/view/handler/EdgeHandler.ts @@ -833,7 +833,7 @@ class EdgeHandler { } } - if (this.isAddVirtualBendEvent(me)) { + if (this.virtualBends && this.isAddVirtualBendEvent(me)) { for (let i = 0; i < this.virtualBends.length; i += 1) { if (checkShape(this.virtualBends[i])) { result = InternalEvent.VIRTUAL_HANDLE - i; @@ -1468,7 +1468,7 @@ class EdgeHandler { // Sets the color of the preview to valid or invalid, updates the // points of the preview and redraws - const color = + const color = this.error == null ? this.marker.validColor : this.marker.invalidColor; this.setPreviewColor(color); this.abspoints = clone.absolutePoints; @@ -1579,10 +1579,13 @@ class EdgeHandler { edge = cloned; } - edge = this.connect(edge, terminal, this.isSource, clone, me); + } finally { + + model.endUpdate(); + } } else if (this.graph.isAllowDanglingEdges()) { const pt = this.abspoints[ @@ -2227,14 +2230,20 @@ class EdgeHandler { this.abspoints = this.getSelectionPoints(this.state); this.points = []; + if (this.bends.length){ this.destroyBends(this.bends); this.bends = this.createBends(); + } + if (this.virtualBends.length){ this.destroyBends(this.virtualBends); this.virtualBends = this.createVirtualBends(); + } + if (this.customHandles.length){ this.destroyBends(this.customHandles); this.customHandles = this.createCustomHandles(); + } // Puts label node on top of bends if ( diff --git a/packages/core/src/view/handler/KeyHandler.ts b/packages/core/src/view/handler/KeyHandler.ts index 3e112835d2..dbc6023d85 100644 --- a/packages/core/src/view/handler/KeyHandler.ts +++ b/packages/core/src/view/handler/KeyHandler.ts @@ -70,6 +70,7 @@ import CellEditorHandler from './CellEditorHandler'; */ class KeyHandler { constructor(graph: Graph, target: Element | null=null) { + if (graph != null) { this.graph = graph; this.target = target || document.documentElement; @@ -207,7 +208,7 @@ class KeyHandler { } if (isShiftDown(evt)) { return this.shiftKeys[evt.keyCode]; - } + } return this.normalKeys[evt.keyCode]; } @@ -250,6 +251,7 @@ class KeyHandler { * @param evt Key event that represents the keystroke. */ keyDown(evt: KeyboardEvent) { + if (this.isEnabledForEvent(evt)) { // Cancels the editing if escape is pressed if (evt.keyCode === 27 /* Escape */) { @@ -259,7 +261,6 @@ class KeyHandler { // Invokes the function for the keystroke else if (!this.isEventIgnored(evt)) { const boundFunction = this.getFunction(evt); - if (boundFunction != null) { boundFunction(evt); InternalEvent.consume(evt); diff --git a/packages/core/src/view/handler/SelectionCellsHandler.ts b/packages/core/src/view/handler/SelectionCellsHandler.ts index b2da783c3d..11c9f09996 100644 --- a/packages/core/src/view/handler/SelectionCellsHandler.ts +++ b/packages/core/src/view/handler/SelectionCellsHandler.ts @@ -51,7 +51,7 @@ class SelectionCellsHandler extends EventSource implements GraphPlugin { } }; - this.graph.addListener(InternalEvent.CHANGE, this.refreshHandler); + this.graph.getSelectionModel().addListener(InternalEvent.CHANGE, this.refreshHandler); this.graph.getDataModel().addListener(InternalEvent.CHANGE, this.refreshHandler); this.graph.getView().addListener(InternalEvent.SCALE, this.refreshHandler); this.graph.getView().addListener(InternalEvent.TRANSLATE, this.refreshHandler); @@ -143,7 +143,7 @@ class SelectionCellsHandler extends EventSource implements GraphPlugin { const tmp = sortCells(this.getHandledSelectionCells(), false); // Destroys or updates old handlers - for (let i = 0; i < tmp.length; i += 1) { + for (let i= 0; i < tmp.length; i++) { const state = this.graph.view.getState(tmp[i]); if (state) { @@ -174,7 +174,7 @@ class SelectionCellsHandler extends EventSource implements GraphPlugin { }); // Creates new handlers and updates parent highlight on existing handlers - for (let i = 0; i < tmp.length; i += 1) { + for (let i = 0; i < tmp.length; i++) { const state = this.graph.view.getState(tmp[i]); if (state) { diff --git a/packages/core/src/view/handler/SelectionHandler.ts b/packages/core/src/view/handler/SelectionHandler.ts index ea9ee63109..e2164faa16 100644 --- a/packages/core/src/view/handler/SelectionHandler.ts +++ b/packages/core/src/view/handler/SelectionHandler.ts @@ -208,7 +208,7 @@ class SelectionHandler implements GraphPlugin { * Specifies if other cells should be used for snapping the right, center or * left side of the current selection. Default is false. */ - guidesEnabled = false; + guidesEnabled = true; /** * Whether the handles of the selection are currently visible. @@ -300,7 +300,7 @@ class SelectionHandler implements GraphPlugin { /** * Maximum number of cells for which live preview should be used. Default is 0 which means no live preview. */ - maxLivePreview = 0; + maxLivePreview = 50; /** * Variable allowLivePreview @@ -326,8 +326,8 @@ class SelectionHandler implements GraphPlugin { target: Cell | null = null; suspended = false; - livePreviewActive = false; - livePreviewUsed = false; + livePreviewActive = true; + livePreviewUsed = true; highlight: CellHighlight | null = null; @@ -743,8 +743,8 @@ class SelectionHandler implements GraphPlugin { for (let i = 0; i < this.cells.length; i += 1) { this.cellCount += this.addStates(this.cells[i], this.allCells); } - if (this.guidesEnabled) { + this.guide = this.createGuide(); const parent = cell.getParent() as Cell; const ignore = parent.getChildCount() < 2; diff --git a/packages/core/src/view/handler/VertexHandler.ts b/packages/core/src/view/handler/VertexHandler.ts index ba77609509..cedbb9e625 100644 --- a/packages/core/src/view/handler/VertexHandler.ts +++ b/packages/core/src/view/handler/VertexHandler.ts @@ -612,7 +612,7 @@ class VertexHandler { if (!me.isConsumed() && this.graph.isEnabled()) { const handle = this.getHandleForEvent(me); - if (handle) { + if (handle!=null) { this.start(me.getGraphX(), me.getGraphY(), handle); me.consume(); } diff --git a/packages/core/src/view/mixins/CellsMixin.ts b/packages/core/src/view/mixins/CellsMixin.ts index 2a1a96217b..b08758d3e1 100644 --- a/packages/core/src/view/mixins/CellsMixin.ts +++ b/packages/core/src/view/mixins/CellsMixin.ts @@ -842,7 +842,7 @@ export const CellsMixin: PartialType = { * be updated to reflect the lost parent cell. Default is `false`. */ // cloneCell(cell: mxCell, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; - cloneCell(cell, allowInvalidEdges = false, mapping = null, keepPosition = false) { + cloneCell(cell, allowInvalidEdges = false, mapping = {}, keepPosition = false) { return this.cloneCells( new CellArray(cell), allowInvalidEdges, @@ -2488,7 +2488,7 @@ export const CellsMixin: PartialType = { * @param recurse boolean whether or not to recurse the child ancestors */ isValidAncestor(cell, parent, recurse = false) { - return recurse ? parent.isAncestor(cell) : cell.getParent() === parent; + return recurse ? parent.isAncestor(cell) : cell?.getParent() === parent; }, /***************************************************************************** @@ -2778,7 +2778,9 @@ export const CellsMixin: PartialType = { * @param cell {@link mxCell} whose bendable state should be returned. */ isCellBendable(cell) { + const style = this.getCurrentCellStyle(cell); + return this.isCellsBendable() && !this.isCellLocked(cell) && !!style.bendable; }, diff --git a/packages/core/src/view/mixins/ConnectionsMixin.ts b/packages/core/src/view/mixins/ConnectionsMixin.ts index 1fb0ad6c11..915e20dcd3 100644 --- a/packages/core/src/view/mixins/ConnectionsMixin.ts +++ b/packages/core/src/view/mixins/ConnectionsMixin.ts @@ -265,8 +265,7 @@ const ConnectionsMixin: PartialType = { let dy = 0; if (point) { - perimeter = edge.style[source ? 'exitPerimeter' : 'entryPerimeter'] || false; - + perimeter = edge.style[source ? 'exitPerimeter' : 'entryPerimeter'] || true; // Add entry/exit offset dx = edge.style[source ? 'exitDx' : 'entryDx']; dy = edge.style[source ? 'exitDy' : 'entryDy']; diff --git a/packages/core/src/view/mixins/EdgeMixin.ts b/packages/core/src/view/mixins/EdgeMixin.ts index 441b8efe3c..fcb5b54b30 100644 --- a/packages/core/src/view/mixins/EdgeMixin.ts +++ b/packages/core/src/view/mixins/EdgeMixin.ts @@ -572,23 +572,14 @@ const EdgeMixin: PartialType = { for (let i = 0; i < edges.length; i += 1) { const state = this.getView().getState(edges[i]); - - const source = state - ? state.getVisibleTerminal(true) - : this.getView().getVisibleTerminal(edges[i], true); - const target = state - ? state.getVisibleTerminal(false) - : this.getView().getVisibleTerminal(edges[i], false); + const source = this.getView().getVisibleTerminal(edges[i], true); + const target = this.getView().getVisibleTerminal(edges[i], false); if ( - (includeLoops && source === target) || + (includeLoops && source && target && source === target) || (source !== target && - ((incoming && - target === cell && - (!parent || this.isValidAncestor(source, parent, recurse))) || - (outgoing && - source === cell && - (!parent || this.isValidAncestor(target, parent, recurse))))) + ((incoming && target === cell && (!parent || this.isValidAncestor(source, parent, recurse))) || + (outgoing && source === cell && (!parent || this.isValidAncestor(target, parent, recurse))))) ) { result.push(edges[i]); } diff --git a/packages/core/src/view/mixins/FoldingMixin.ts b/packages/core/src/view/mixins/FoldingMixin.ts index 2a039aadc8..15cbb5a27a 100644 --- a/packages/core/src/view/mixins/FoldingMixin.ts +++ b/packages/core/src/view/mixins/FoldingMixin.ts @@ -92,7 +92,7 @@ type PartialFolding = Pick< | 'updateAlternateBounds' >; type PartialType = PartialGraph & PartialFolding; - +Client.imageBasePath = '/images' // @ts-expect-error The properties of PartialGraph are defined elsewhere. const FoldingMixin: PartialType = { options: { diff --git a/packages/core/src/view/mixins/SwimlaneMixin.ts b/packages/core/src/view/mixins/SwimlaneMixin.ts index cfbefdf25e..00a738262f 100644 --- a/packages/core/src/view/mixins/SwimlaneMixin.ts +++ b/packages/core/src/view/mixins/SwimlaneMixin.ts @@ -359,12 +359,11 @@ const SwimlaneMixin: PartialType = { ) { cell = cell.getParent(); } - + let parent = cell; // Checks if parent is dropped into child if not cloning if (!clone) { - let parent = cell; while (parent && cells.indexOf(parent) < 0) { - parent = parent.getParent(); + parent = parent.getParent(); } } diff --git a/packages/core/src/view/other/Multiplicity.ts b/packages/core/src/view/other/Multiplicity.ts index e02883e6cc..64dddabb22 100644 --- a/packages/core/src/view/other/Multiplicity.ts +++ b/packages/core/src/view/other/Multiplicity.ts @@ -132,7 +132,7 @@ class Multiplicity { */ check( graph: Graph, - edge: Cell, + edge: Cell|null, source: Cell, target: Cell, sourceOut: number, @@ -172,7 +172,7 @@ class Multiplicity { * Checks if there are any valid neighbours in {@link validNeighbors}. This is only * called if {@link validNeighbors} is a non-empty array. */ - checkNeighbors(graph: Graph, edge: Cell, source: Cell, target: Cell): boolean { + checkNeighbors(graph: Graph, edge: Cell|null, source: Cell, target: Cell): boolean { const sourceValue = source.getValue(); const targetValue = target.getValue(); let isValid = !this.validNeighborsAllowed; @@ -196,7 +196,7 @@ class Multiplicity { * given cell is the source or target of the given edge, depending on * {@link source}. This implementation uses {@link checkType} on the terminal's value. */ - checkTerminal(graph: Graph, edge: Cell, terminal: Cell): boolean { + checkTerminal(graph: Graph, terminal: Cell, edge: Cell|null): boolean { const value = terminal.getValue(); return this.checkType(graph, value, this.type, this.attr, this.value); diff --git a/packages/core/src/view/other/Outline.ts b/packages/core/src/view/other/Outline.ts index bc26600e79..245e221a7e 100644 --- a/packages/core/src/view/other/Outline.ts +++ b/packages/core/src/view/other/Outline.ts @@ -71,10 +71,11 @@ import { Listenable } from '../../types'; class Outline { constructor(source: Graph, container: HTMLElement | null = null) { this.source = source; - if (container != null) { this.init(container); + } + } /** diff --git a/packages/core/src/view/other/PrintPreview.ts b/packages/core/src/view/other/PrintPreview.ts index a3ffacbf02..76258cf103 100644 --- a/packages/core/src/view/other/PrintPreview.ts +++ b/packages/core/src/view/other/PrintPreview.ts @@ -403,9 +403,9 @@ class PrintPreview { doc.writeln(''); doc.writeln(''); - if (css) { - this.writeHead(doc, css); - } + + this.writeHead(doc, css); + doc.writeln(''); doc.writeln(''); } @@ -577,7 +577,7 @@ class PrintPreview { */ addPageBreak(doc: Document): void { const hr = doc.createElement('hr'); - hr.className = 'mxPageBreak'; + hr.className = 'PageBreak'; doc.body.appendChild(hr); } @@ -606,7 +606,7 @@ class PrintPreview { * Writes the HEAD section into the given document, without the opening * and closing HEAD tags. */ - writeHead(doc: Document, css: string): void { + writeHead(doc: Document, css: string|null): void { if (this.title != null) { doc.writeln(`${this.title}`); } @@ -852,7 +852,7 @@ class PrintPreview { // Checks clipping rectangle for speedup // Must create terminal states for edge clipping even if terminal outside of clip - this.graph.cellRenderer.redraw = (state, force, rendering) => { + this.graph.cellRenderer.redraw = function(state, force, rendering) { if (state != null) { // Gets original state from graph to find bounding box const orig = states.get(state.cell); diff --git a/packages/core/src/view/style/EdgeStyle.ts b/packages/core/src/view/style/EdgeStyle.ts index 76124f1071..91533e8971 100644 --- a/packages/core/src/view/style/EdgeStyle.ts +++ b/packages/core/src/view/style/EdgeStyle.ts @@ -34,7 +34,7 @@ import Geometry from '../geometry/Geometry'; * * ```javascript * let style = stylesheet.getDefaultEdgeStyle(); - * style.edge = mxEdgeStyle.ElbowConnector; + * style.edgeStyle = mxEdgeStyle.ElbowConnector; * ``` * * Sets the default edge style to . @@ -87,7 +87,7 @@ import Geometry from '../geometry/Geometry'; * * ```javascript * let style = graph.getStylesheet().getDefaultEdgeStyle(); - * style.edge = mxEdgeStyle.MyStyle; + * style.edgeStyle = mxEdgeStyle.MyStyle; * ``` * * Note that the object can be used directly when programmatically setting diff --git a/packages/core/src/view/style/Stylesheet.ts b/packages/core/src/view/style/Stylesheet.ts index 12dc6b722c..0b8b8cd064 100644 --- a/packages/core/src/view/style/Stylesheet.ts +++ b/packages/core/src/view/style/Stylesheet.ts @@ -41,7 +41,7 @@ import type { CellStateStyle, CellStyle } from '../../types'; * var vertexStyle = stylesheet.getDefaultVertexStyle(); * vertexStyle.rounded = true; * var edgeStyle = stylesheet.getDefaultEdgeStyle(); - * edgeStyle.edge = mxEdgeStyle.EntityRelation; + * edgeStyle.edgeStyle = mxEdgeStyle.EntityRelation; * ``` * * Modifies the built-in default styles. diff --git a/packages/core/src/view/undoable_changes/SelectionChange.ts b/packages/core/src/view/undoable_changes/SelectionChange.ts index 85b06529b6..ccfad99aec 100644 --- a/packages/core/src/view/undoable_changes/SelectionChange.ts +++ b/packages/core/src/view/undoable_changes/SelectionChange.ts @@ -49,7 +49,7 @@ class SelectionChange implements UndoableChange { window.status = Translations.get(selectionModel.doneResource) || selectionModel.doneResource; - this.graph.fireEvent( + this.graph.getSelectionModel().fireEvent( new EventObject(InternalEvent.CHANGE, { added: this.added, removed: this.removed }) ); } diff --git a/packages/core/typed_mxgraph_defs.json b/packages/core/typed_mxgraph_defs.json index 16b6cacad7..f06602193f 100644 --- a/packages/core/typed_mxgraph_defs.json +++ b/packages/core/typed_mxgraph_defs.json @@ -855,7 +855,7 @@ " * var vertexStyle = stylesheet.getDefaultVertexStyle();", " * vertexStyle.rounded = true;", " * var edgeStyle = stylesheet.getDefaultEdgeStyle();", - " * edgeStyle.edge = mxEdgeStyle.EntityRelation;", + " * edgeStyle.edgeStyle = mxEdgeStyle.EntityRelation;", " * ```", " *", " * Modifies the built-in default styles.", diff --git a/packages/html/package.json b/packages/html/package.json index cdfe97068c..08f7c3ee66 100644 --- a/packages/html/package.json +++ b/packages/html/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "dev": "start-storybook -p 8901" + "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider start-storybook -p 8901 ./public" }, "author": "", "license": "ISC", diff --git a/packages/html/public/fileio.txt b/packages/html/public/fileio.txt index 012410a5ba..d75934f52a 100644 --- a/packages/html/public/fileio.txt +++ b/packages/html/public/fileio.txt @@ -1,19 +1,19 @@ # Custom file format for fileio.html (comments start with #, all vertices first) # Vertices (id: label) -1:
Last, First
Status
Info -2:
Errorcode
Status
Info -3:
Warning
Status
Info -4:
Groupname
Status
Info -5:
Workplace
Status
Info -6:
Information
Status
Info -7:
Printername
Status
Info +1:
Last, First
Status
Info +2:
Errorcode
Status
Info +3:
Warning
Status
Info +4:
Groupname
Status
Info +5:
Workplace
Status
Info +6:
Information
Status
Info +7:
Printername
Status
Info # Edges (source-id,target-id: label) -1,2: Hint -1,3: News -1,4: Member -5,6: Details -5,7: Access -4,5: Access -1,5: 2-Way +1,2: Hint +1,3: News +1,4: Member +5,6: Details +5,7: Access +4,5: Access +1,5: 2-Way diff --git a/packages/html/public/images/check.png b/packages/html/public/images/check.png index ce81bceb7a..3f3110a14f 100644 Binary files a/packages/html/public/images/check.png and b/packages/html/public/images/check.png differ diff --git a/packages/html/public/images/error.png b/packages/html/public/images/error.png new file mode 100644 index 0000000000..eb1491b416 Binary files /dev/null and b/packages/html/public/images/error.png differ diff --git a/packages/html/public/images/flash.png b/packages/html/public/images/flash.png new file mode 100644 index 0000000000..aa6fd2d1e9 Binary files /dev/null and b/packages/html/public/images/flash.png differ diff --git a/packages/html/public/images/forbidden.png b/packages/html/public/images/forbidden.png new file mode 100644 index 0000000000..04d5f4ab19 Binary files /dev/null and b/packages/html/public/images/forbidden.png differ diff --git a/packages/html/public/images/help.png b/packages/html/public/images/help.png new file mode 100644 index 0000000000..e8ceddb370 Binary files /dev/null and b/packages/html/public/images/help.png differ diff --git a/packages/html/public/images/information.png b/packages/html/public/images/information.png new file mode 100644 index 0000000000..5df1857444 Binary files /dev/null and b/packages/html/public/images/information.png differ diff --git a/packages/html/public/images/keys.png b/packages/html/public/images/keys.png new file mode 100644 index 0000000000..41828e4290 Binary files /dev/null and b/packages/html/public/images/keys.png differ diff --git a/packages/html/public/images/lightbulb_on.png b/packages/html/public/images/lightbulb_on.png new file mode 100644 index 0000000000..8b594120dd Binary files /dev/null and b/packages/html/public/images/lightbulb_on.png differ diff --git a/packages/html/public/images/pencil.png b/packages/html/public/images/pencil.png new file mode 100644 index 0000000000..712443eb68 Binary files /dev/null and b/packages/html/public/images/pencil.png differ diff --git a/packages/html/public/images/user3.png b/packages/html/public/images/user3.png new file mode 100644 index 0000000000..7e83258336 Binary files /dev/null and b/packages/html/public/images/user3.png differ diff --git a/packages/html/public/images/users3.png b/packages/html/public/images/users3.png new file mode 100644 index 0000000000..2185bf46ca Binary files /dev/null and b/packages/html/public/images/users3.png differ diff --git a/packages/html/stories/Anchors.stories.js b/packages/html/stories/Anchors.stories.js index acfc47e8e0..f8cb26c1cc 100644 --- a/packages/html/stories/Anchors.stories.js +++ b/packages/html/stories/Anchors.stories.js @@ -4,14 +4,24 @@ import { RubberBandHandler, ConnectionHandler, ConnectionConstraint, - Geometry, + Shape, PolylineShape, Point, CellState, + Client } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; +import SelectionCellsHandler from '../../core/src/view/handler/SelectionCellsHandler'; + +import SelectionHandler from '../../core/src/view/handler/SelectionHandler'; +import PanningHandler from '../../core/src/view/handler/PanningHandler'; +import PopupMenuHandler from '../../core/src/view/handler/PopupMenuHandler'; +import CellEditorHandler from '../../core/src/view/handler/CellEditorHandler'; +import TooltipHandler from '../../core/src/view/handler/TooltipHandler'; + + export default { title: 'Connections/Anchors', argTypes: { @@ -32,6 +42,7 @@ const Template = ({ label, ...args }) => { container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; + Client.imageBasePath = '/images' if (!args.contextMenu) InternalEvent.disableContextMenu(container); class MyCustomConnectionHandler extends ConnectionHandler { @@ -39,9 +50,24 @@ const Template = ({ label, ...args }) => { createEdgeState(me) { const edge = graph.createEdge(null, null, null, null, null); return new CellState(this.graph.view, edge, this.graph.getCellStyle(edge)); - } + } } + // Defines the default constraints for the vertices + Shape.prototype.constraints = [ + new ConnectionConstraint(new Point(0.25, 0), true), + new ConnectionConstraint(new Point(0.5, 0), true), + new ConnectionConstraint(new Point(0.75, 0), true), + new ConnectionConstraint(new Point(0, 0.25), true), + new ConnectionConstraint(new Point(0, 0.5), true), + new ConnectionConstraint(new Point(0, 0.75), true), + new ConnectionConstraint(new Point(1, 0.25), true), + new ConnectionConstraint(new Point(1, 0.5), true), + new ConnectionConstraint(new Point(1, 0.75), true), + new ConnectionConstraint(new Point(0.25, 1), true), + new ConnectionConstraint(new Point(0.5, 1), true), + new ConnectionConstraint(new Point(0.75, 1), true), + ]; class MyCustomGraph extends Graph { getAllConnectionConstraints(terminal, source) { // Overridden to define per-geometry connection points @@ -63,33 +89,28 @@ const Template = ({ label, ...args }) => { } } - class MyCustomGeometryClass extends Geometry { - // Defines the default constraints for the vertices - constraints = [ - new ConnectionConstraint(new Point(0.25, 0), true), - new ConnectionConstraint(new Point(0.5, 0), true), - new ConnectionConstraint(new Point(0.75, 0), true), - new ConnectionConstraint(new Point(0, 0.25), true), - new ConnectionConstraint(new Point(0, 0.5), true), - new ConnectionConstraint(new Point(0, 0.75), true), - new ConnectionConstraint(new Point(1, 0.25), true), - new ConnectionConstraint(new Point(1, 0.5), true), - new ConnectionConstraint(new Point(1, 0.75), true), - new ConnectionConstraint(new Point(0.25, 1), true), - new ConnectionConstraint(new Point(0.5, 1), true), - new ConnectionConstraint(new Point(0.75, 1), true), - ]; - } - + const plugins = [ + CellEditorHandler, + TooltipHandler, + SelectionCellsHandler, + PopupMenuHandler, + MyCustomConnectionHandler, + SelectionHandler, + PanningHandler, + ]; + // Edges have no connection points PolylineShape.prototype.constraints = null; // Creates the graph inside the given container - const graph = new MyCustomGraph(container); + const graph = new MyCustomGraph(container, null, plugins); graph.setConnectable(true); // Specifies the default edge style graph.getStylesheet().getDefaultEdgeStyle().edgeStyle = 'orthogonalEdgeStyle'; + graph.getStylesheet().getDefaultEdgeStyle().bendable = true; + + // Enables rubberband selection if (args.rubberBand) new RubberBandHandler(graph); @@ -105,14 +126,14 @@ const Template = ({ label, ...args }) => { value: 'Hello,', position: [20, 20], size: [80, 30], - geometryClass: MyCustomGeometryClass, +// geometryClass: MyCustomGeometryClass, }); const v2 = graph.insertVertex({ parent, value: 'World!', position: [200, 150], size: [80, 30], - geometryClass: MyCustomGeometryClass, +// geometryClass: MyCustomGeometryClass, }); const e1 = graph.insertEdge({ parent, diff --git a/packages/html/stories/AutoLayout.stories.js b/packages/html/stories/AutoLayout.stories.js index 1c8144ee59..638ce3eba1 100644 --- a/packages/html/stories/AutoLayout.stories.js +++ b/packages/html/stories/AutoLayout.stories.js @@ -14,6 +14,7 @@ import { eventUtils, mathUtils, } from '@maxgraph/core'; +import { convertPoint } from '../../core/src/util/styleUtils'; import { globalTypes } from '../.storybook/preview'; @@ -83,6 +84,7 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given this.el const graph = new MyCustomGraph(container); graph.setPanning(true); + graph.getStylesheet().getDefaultEdgeStyle().bendable = true; const panningHandler = graph.getPlugin('PanningHandler'); panningHandler.useLeftButtonForPanning = true; @@ -173,7 +175,7 @@ const Template = ({ label, ...args }) => { graph.stopEditing(false); - const pt = mathUtils.convertPoint( + const pt = convertPoint( graph.container, eventUtils.getClientX(evt2), eventUtils.getClientY(evt2) diff --git a/packages/html/stories/Boundary.stories.js b/packages/html/stories/Boundary.stories.js index 9404ba5e26..8dfd6ff0c1 100644 --- a/packages/html/stories/Boundary.stories.js +++ b/packages/html/stories/Boundary.stories.js @@ -8,6 +8,7 @@ import { } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; +import { convertPoint } from '../../core/src/util/styleUtils'; export default { title: 'Events/Boundary', @@ -142,7 +143,7 @@ const Template = ({ label, ...args }) => { // Replaces move preview for relative children graphHandler.getDelta = function (me) { - const point = mathUtils.convertPoint(this.graph.container, me.getX(), me.getY()); + const point = convertPoint(this.graph.container, me.getX(), me.getY()); let delta = new Point(point.x - this.first.x, point.y - this.first.y); if (this.cells != null && this.cells.length > 0 && this.cells[0] != null) { diff --git a/packages/html/stories/Clipboard.stories.js b/packages/html/stories/Clipboard.stories.js index 58a648a028..375679f2a6 100644 --- a/packages/html/stories/Clipboard.stories.js +++ b/packages/html/stories/Clipboard.stories.js @@ -17,15 +17,7 @@ import { globalTypes } from '../.storybook/preview'; export default { title: 'DnD_CopyPaste/Clipboard', argTypes: { - ...globalTypes, - contextMenu: { - type: 'boolean', - defaultValue: false, - }, - rubberBand: { - type: 'boolean', - defaultValue: true, - }, + ...globalTypes }, }; @@ -69,12 +61,11 @@ const Template = ({ label, ...args }) => { // Workaround for no copy event in IE/FF if empty textInput.value = ' '; - - // Shows a textare when control/cmd is pressed to handle native clipboard actions + // Shows a textarea when control/cmd is pressed to handle native clipboard actions InternalEvent.addListener(document, 'keydown', function (evt) { // No dialog visible - const source = eventUtils.getSource(evt); + const source = eventUtils.getSource(evt); if ( graph.isEnabled() && !graph.isMouseDown && @@ -82,6 +73,7 @@ const Template = ({ label, ...args }) => { source.nodeName !== 'INPUT' ) { if ( + evt.keyCode === 224 /* FF */ || (!Client.IS_MAC && evt.keyCode === 17) /* Control */ || (Client.IS_MAC && @@ -154,7 +146,7 @@ const Template = ({ label, ...args }) => { if (graph.isEnabled() && !graph.isSelectionEmpty()) { copyCells( graph, - utils.sortCells(graph.model.getTopmostCells(graph.getSelectionCells())) + styleUtils.sortCells(graph.getSelectionCells().getTopmostCells()) ); dx = 0; dy = 0; @@ -175,54 +167,52 @@ const Template = ({ label, ...args }) => { dx = dx != null ? dx : 0; dy = dy != null ? dy : 0; let cells = []; - - try { - const doc = utils.parseXml(xml); - const node = doc.documentElement; + + + const node = xmlUtils.parseXml(xml); if (node != null) { const model = new GraphDataModel(); const codec = new Codec(node.ownerDocument); + codec.decode(node, model); const childCount = model.getRoot().getChildCount(); const targetChildCount = graph.model.getRoot().getChildCount(); - // Merges existing layers and adds new layers graph.model.beginUpdate(); - try { - for (let i = 0; i < childCount; i++) { - let parent = model.getRoot().getChildAt(i); - + + + for (var i = 0; i < childCount; i++) + { + var parent = model.getRoot().getChildAt(i); + // Adds cells to existing layers if not locked - if (targetChildCount > i) { + if (targetChildCount > i) + { // Inserts into active layer if only one layer is being pasted - const target = - childCount === 1 - ? graph.getDefaultParent() - : graph.model.getRoot().getChildAt(i); - - if (!graph.isCellLocked(target)) { - const children = parent.getChildren(); + var target = (childCount == 1) ? graph.getDefaultParent() : graph.model.getRoot().getChildAt(i); + + if (!graph.isCellLocked(target)) + { + var children = parent.getChildren(); cells = cells.concat(graph.importCells(children, dx, dy, target)); } - } else { + } + else + { // Delta is non cascading, needs separate move for layers parent = graph.importCells([parent], 0, 0, graph.model.getRoot())[0]; - const children = parent.getChildren(); + var children = graph.model.getChildren(parent); graph.moveCells(children, dx, dy); cells = cells.concat(children); } } - } finally { + graph.model.endUpdate(); - } - } - } catch (e) { - alert(e); - throw e; - } - + + + } return cells; }; @@ -242,11 +232,12 @@ const Template = ({ label, ...args }) => { dy += gs; } + // Standard paste via control-v - if (xml.substring(0, 14) === '') { + // if (xml.substring(0, 14) === '') { graph.setSelectionCells(importXml(xml, dx, dy)); graph.scrollCellToVisible(graph.getSelectionCell()); - } + // } } }; @@ -261,7 +252,7 @@ const Template = ({ label, ...args }) => { data = provider.types.indexOf('text/html') >= 0 ? provider.getData('text/html') : null; - if (provider.types.indexOf('text/plain') && (data == null || data.length === 0)) { + if (provider.types.indexOf('text/plain' && (data == null || data.length === 0))) { data = provider.getData('text/plain'); } } @@ -316,7 +307,6 @@ const Template = ({ label, ...args }) => { }); const e1 = graph.insertEdge({ parent, source: v1, target: v2 }); }); - return container; }; diff --git a/packages/html/stories/Collapse.stories.js b/packages/html/stories/Collapse.stories.js index 0ad36baa64..24da5e1054 100644 --- a/packages/html/stories/Collapse.stories.js +++ b/packages/html/stories/Collapse.stories.js @@ -1,4 +1,4 @@ -import { Graph, Rectangle } from '@maxgraph/core'; +import { Graph, Rectangle,Client } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,6 +18,8 @@ const Template = ({ label, ...args }) => { container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; + Client.imageBasePath = '/images' + const graph = new Graph(container); const parent = graph.getDefaultParent(); @@ -25,7 +27,7 @@ const Template = ({ label, ...args }) => { // Extends Transactions.getStyle to show an image when collapsed // TODO cannot use super without a parent class // let style = super.getStyle(); - let style = ''; + let style = this.style; if (this.isCollapsed()) { style = { ...style, @@ -45,7 +47,11 @@ const Template = ({ label, ...args }) => { value: 'Container', position: [20, 20], size: [200, 200], - style: { shape: 'swimlane', startSize: 20 }, + style: { + shape: 'swimlane', + startSize: 20, + foldable: true, + } }); v1.geometry.alternateBounds = new Rectangle(0, 0, 110, 70); v1.getStyle = getStyle; diff --git a/packages/html/stories/ContextIcons.stories.js b/packages/html/stories/ContextIcons.stories.js index bbb578d2e0..ef903fa21b 100644 --- a/packages/html/stories/ContextIcons.stories.js +++ b/packages/html/stories/ContextIcons.stories.js @@ -3,10 +3,10 @@ import { InternalEvent, RubberBandHandler, eventUtils, - mathUtils, domUtils, VertexHandler, } from '@maxgraph/core'; +import { convertPoint } from '../../core/src/util/styleUtils'; import { globalTypes } from '../.storybook/preview'; @@ -30,15 +30,20 @@ const Template = ({ label, ...args }) => { container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; - class mxVertexToolHandler extends VertexHandler { + class MyVertexToolHandler extends VertexHandler { // Defines a subclass for VertexHandler that adds a set of clickable // icons to every selected vertex. - - domNode = null; + + constructor(state){ + if (state){ + super(state) + this.state=state + this.domNode = null; + this.init() + } + } init() { - super.init(); - // In this example we force the use of DIVs for images in IE. This // handles transparency in PNG images properly in IE and fixes the // problem that IE routes all mouse events for a gesture via the @@ -114,7 +119,7 @@ const Template = ({ label, ...args }) => { img.style.height = '16px'; InternalEvent.addGestureListeners(img, (evt) => { - const pt = mathUtils.convertPoint( + const pt = convertPoint( this.graph.container, eventUtils.getClientX(evt), eventUtils.getClientY(evt) @@ -143,8 +148,8 @@ const Template = ({ label, ...args }) => { } } - destroy(sender, me) { - super.destroy(sender, me); + onDestroy(sender, me) { + super.onDestroy(sender, me); if (this.domNode != null) { this.domNode.parentNode.removeChild(this.domNode); @@ -156,7 +161,7 @@ const Template = ({ label, ...args }) => { class MyCustomGraph extends Graph { createHandler(state) { if (state != null && state.cell.isVertex()) { - return new mxVertexToolHandler(state); + return new MyVertexToolHandler(state); } return super.createHandler(state); } diff --git a/packages/html/stories/DragSource.stories.js b/packages/html/stories/DragSource.stories.js index 412e5a77f7..0348b8c0f5 100644 --- a/packages/html/stories/DragSource.stories.js +++ b/packages/html/stories/DragSource.stories.js @@ -163,7 +163,7 @@ const Template = ({ label, ...args }) => { // Redirects feature to global switch. Note that this feature should only be used // if the the x and y arguments are used in funct to insert the cell. ds.isGuidesEnabled = () => { - return graphs[0].graphHandler.guidesEnabled; + return graphs[0].pluginsMap['SelectionHandler'].guidesEnabled; }; // Restores original drag icon while outside of graph diff --git a/packages/html/stories/DynamicLoading.stories.js b/packages/html/stories/DynamicLoading.stories.js index 64eb469cae..447855f8e5 100644 --- a/packages/html/stories/DynamicLoading.stories.js +++ b/packages/html/stories/DynamicLoading.stories.js @@ -35,6 +35,9 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given container const graph = new Graph(container); + const width = args.width + const height = args.height + // Disables all built-in interactions graph.setEnabled(false); @@ -50,15 +53,15 @@ const Template = ({ label, ...args }) => { // Changes the default vertex style in-place const style = graph.getStylesheet().getDefaultVertexStyle(); style.shape = constants.SHAPE.ELLIPSE; - style.perimiter = Perimeter.EllipsePerimeter; + style.perimeter = Perimeter.EllipsePerimeter; style.gradientColor = 'white'; // 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 cx = graph.container.clientWidth / 2; - const cy = graph.container.clientHeight / 2; + const cx = width / 2; + const cy = height / 2; const cell = graph.insertVertex(parent, '0-0', '0-0', cx - 20, cy - 15, 60, 40); @@ -73,8 +76,8 @@ const Template = ({ label, ...args }) => { // (implemented for this demo using the server-function) function load(graph, cell) { if (cell.isVertex()) { - const cx = graph.container.clientWidth / 2; - const cy = graph.container.clientHeight / 2; + const cx = width / 2; + const cy = height / 2; // Gets the default parent for inserting new cells. This // is normally the first child of the root (ie. layer 0). @@ -85,7 +88,7 @@ const Template = ({ label, ...args }) => { const xml = server(cell.id); const doc = xmlUtils.parseXml(xml); const dec = new Codec(doc); - const model = dec.decode(doc.documentElement); + const model = dec.decode(doc); // Removes all cells which are not in the response for (var key in graph.getDataModel().cells) { @@ -97,7 +100,7 @@ const Template = ({ label, ...args }) => { } // Merges the response model with the client model - graph.getDataModel().mergeChildren(graph.getDataModel().getRoot().getChildAt(0), parent); + graph.getDataModel().mergeChildren(model.getRoot().getChildAt(0), parent); // Moves the given cell to the center let geo = cell.getGeometry(); @@ -138,8 +141,8 @@ const Template = ({ label, ...args }) => { const cellCount = vertices.length; const phi = (2 * Math.PI) / cellCount; const r = Math.min( - graph.container.clientWidth / 4, - graph.container.clientHeight / 4 + width / 3, + height / 3 ); for (let i = 0; i < cellCount; i++) { @@ -153,7 +156,11 @@ const Template = ({ label, ...args }) => { graph.getDataModel().setGeometry(vertices[i], geo); } } - }); + console.log('finishedOnLoad') + } + + ); + } } diff --git a/packages/html/stories/DynamicStyle.stories.js b/packages/html/stories/DynamicStyle.stories.js index cb14992aa4..788400bd37 100644 --- a/packages/html/stories/DynamicStyle.stories.js +++ b/packages/html/stories/DynamicStyle.stories.js @@ -43,7 +43,7 @@ const Template = ({ label, ...args }) => { const getStyle = function () { // TODO super cannot be used here // let style = super.getStyle(); - let style = {}; + let style = this.style; if (this.isEdge()) { const target = this.getTerminal(false); diff --git a/packages/html/stories/DynamicToolbar.stories.js b/packages/html/stories/DynamicToolbar.stories.js index 6a375984d2..67eca67417 100644 --- a/packages/html/stories/DynamicToolbar.stories.js +++ b/packages/html/stories/DynamicToolbar.stories.js @@ -37,23 +37,16 @@ const Template = ({ label, ...args }) => { container.style.height = `${args.height}px`; container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; + container.style.marginLeft='10px' div.appendChild(container); - // Defines an icon for creating new connections in the connection handler. - // This will automatically disable the highlighting of the source vertex. - ConnectionHandler.prototype.connectImage = new ImageBox( - '/images/connector.gif', - 16, - 16 - ); - // Creates the div for the toolbar const tbContainer = document.createElement('div'); tbContainer.style.position = 'absolute'; tbContainer.style.overflow = 'hidden'; tbContainer.style.padding = '2px'; tbContainer.style.left = '0px'; - tbContainer.style.top = '0px'; + tbContainer.style.top = '10px'; tbContainer.style.width = '24px'; tbContainer.style.bottom = '0px'; @@ -69,6 +62,10 @@ const Template = ({ label, ...args }) => { const graph = new Graph(container, model); // Enables new connections in the graph + // Defines an icon for creating new connections in the connection handler. + // This will automatically disable the highlighting of the source vertex. + const connectionHandler = graph.getPlugin('ConnectionHandler'); + connectionHandler.connectImage = new ImageBox('images/connector.gif', 16, 16); graph.setConnectable(true); graph.setMultigraph(false); @@ -92,7 +89,7 @@ const Template = ({ label, ...args }) => { const img = addToolbarItem(graph, toolbar, vertex, icon); img.enabled = true; - graph.getSelectionModel().addListener(InternalEvent.CHANGE, () => { + graph.getSelectionModel().addListener(InternalEvent.CHANGE, function () { const tmp = graph.isSelectionEmpty(); styleUtils.setOpacity(img, tmp ? 100 : 20); img.enabled = tmp; diff --git a/packages/html/stories/EdgeTolerance.stories.js b/packages/html/stories/EdgeTolerance.stories.js index 93c16acf32..73bff3d6c7 100644 --- a/packages/html/stories/EdgeTolerance.stories.js +++ b/packages/html/stories/EdgeTolerance.stories.js @@ -70,7 +70,7 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given container const graph = new MyCustomGraph(container); - graph.setEventTolerance(20); + graph.setEventTolerance(200); // Gets the default parent for inserting new cells. This // is normally the first child of the root (ie. layer 0). @@ -96,6 +96,7 @@ const Template = ({ label, ...args }) => { target: v2, style: { edgeStyle: 'orthogonalEdgeStyle', + bendable: true }, }); const e2 = graph.insertEdge({ @@ -104,6 +105,7 @@ const Template = ({ label, ...args }) => { target: v1, style: { edgeStyle: 'orthogonalEdgeStyle', + bendable: true }, }); }); diff --git a/packages/html/stories/Editing.stories.js b/packages/html/stories/Editing.stories.js index 5c0d6fc5f6..ba36182626 100644 --- a/packages/html/stories/Editing.stories.js +++ b/packages/html/stories/Editing.stories.js @@ -6,6 +6,7 @@ import { cloneUtils, eventUtils, } from '@maxgraph/core'; +import { convertPoint } from '../../core/src/util/styleUtils'; import { globalTypes } from '../.storybook/preview'; @@ -77,7 +78,7 @@ const Template = ({ label, ...args }) => { // a mouse event if (evt != null) { // Finds the relative coordinates inside the cell - const point = mathUtils.convertPoint( + const point = convertPoint( this.container, eventUtils.getClientX(evt), eventUtils.getClientY(evt) @@ -129,6 +130,14 @@ const Template = ({ label, ...args }) => { // is normally the first child of the root (ie. layer 0). const parent = graph.getDefaultParent(); + let style = graph.getStylesheet().getDefaultEdgeStyle(); + + style.bendable=true; + style.editable=true + + style = graph.getStylesheet().getDefaultVertexStyle(); + style.editable=true; + // Adds cells to the model in a single step graph.batchUpdate(() => { const v1 = graph.insertVertex({ diff --git a/packages/html/stories/Events.stories.js b/packages/html/stories/Events.stories.js index d2a577e999..587d06deb0 100644 --- a/packages/html/stories/Events.stories.js +++ b/packages/html/stories/Events.stories.js @@ -39,7 +39,6 @@ const Template = ({ label, ...args }) => { class MyCustomConnectionHandler extends ConnectionHandler { // Sets the image to be used for creating new connections - connectImage = new ImageBox('/images/green-dot.gif', 14, 14); } // Disables built-in context menu @@ -65,6 +64,9 @@ const Template = ({ label, ...args }) => { // use new RubberBandHandler(graph) and new KeyHandler(graph). const graph = new MyCustomGraph(container); + const connectionHandler = graph.getPlugin('ConnectionHandler'); + connectionHandler.connectImage = new ImageBox('/images/green-dot.gif', 16, 16); + // Enables tooltips, new connections and panning graph.setPanning(true); graph.setTooltips(true); @@ -90,9 +92,14 @@ const Template = ({ label, ...args }) => { // when the user double clicks on the adjustment control point // of the edge. The ElbowConnector edge style switches to TopToBottom // if the horizontal style is true. - const style = graph.getStylesheet().getDefaultEdgeStyle(); + let style = graph.getStylesheet().getDefaultEdgeStyle(); style.rounded = true; - style.edge = EdgeStyle.ElbowConnector; + style.bendable=true; + style.editable=true + style.edgeStyle = EdgeStyle.ElbowConnector; + + style = graph.getStylesheet().getDefaultVertexStyle(); + style.editable=true; const popupMenuHandler = graph.getPlugin('PopupMenuHandler'); diff --git a/packages/html/stories/ExtendCanvas.stories.js b/packages/html/stories/ExtendCanvas.stories.js index 39ca1c3322..b902eff849 100644 --- a/packages/html/stories/ExtendCanvas.stories.js +++ b/packages/html/stories/ExtendCanvas.stories.js @@ -6,13 +6,13 @@ import { Point, styleUtils, } from '@maxgraph/core'; +import {hasScrollbars} from '../../core/src/util/styleUtils'; import { globalTypes } from '../.storybook/preview'; export default { title: 'Backgrounds/ExtendCanvas', argTypes: { - ...globalTypes, contextMenu: { type: 'boolean', defaultValue: false, @@ -28,8 +28,8 @@ const Template = ({ label, ...args }) => { const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'auto'; - container.style.width = `${args.width}px`; - container.style.height = `${args.height}px`; + container.style.width = '321px'; + container.style.height = '241px'; container.style.cursor = 'default'; container.style.background = 'url(/images/grid.gif)'; @@ -50,8 +50,8 @@ const Template = ({ label, ...args }) => { */ getPagePadding() { return new Point( - Math.max(0, Math.round(this.container.offsetWidth - 34)), - Math.max(0, Math.round(this.container.offsetHeight - 34)) + Math.max(0, Math.round(321 - 34)), + Math.max(0, Math.round(241 - 34)) ); } @@ -97,6 +97,7 @@ const Template = ({ label, ...args }) => { return new Rectangle(x0, y0, w0, h0); } + getPreferredPageSize(bounds, width, height) { const pages = this.getPageLayout(); const size = this.getPageSize(); @@ -104,8 +105,9 @@ const Template = ({ label, ...args }) => { return new Rectangle(0, 0, pages.width * size.width, pages.height * size.height); } - sizeDidChange() { - if (this.container != null && styleUtils.hasScrollbars(this.container)) { + + sizeDidChange() { + if (this.container != null ){//&& hasScrollbars(this.container)) { const pages = this.getPageLayout(); const pad = this.getPagePadding(); const size = this.getPageSize(); diff --git a/packages/html/stories/FileIO.stories.js b/packages/html/stories/FileIO.stories.js index e762677054..0316e05965 100644 --- a/packages/html/stories/FileIO.stories.js +++ b/packages/html/stories/FileIO.stories.js @@ -1,9 +1,10 @@ -import { Graph, constants } from '@maxgraph/core'; +import { Graph, constants, Client, CellTracker, Perimeter, FastOrganicLayout , EventObject, InternalEvent,EventUtils} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; import { clone } from '@maxgraph/core/util/cloneUtils'; import { button } from '@maxgraph/core/util/domHelpers'; import { load } from '@maxgraph/core/util/MaxXmlRequest'; +import { isConsumed } from '../../core/src/util/EventUtils' export default { title: 'Xml_Json/FileIO', @@ -17,17 +18,14 @@ const Template = ({ label, ...args }) => { const container = document.createElement('div'); container.style.position = 'relative'; - container.style.overflow = 'hidden'; + container.style.overflow = 'auto'; 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); - // Program starts here. Creates a sample graph in the - // DOM node with the specified ID. This function is invoked - // from the onLoad event handler of the document (see below). - function main(container) { + // Checks if browser is supported if (!Client.isBrowserSupported()) { // Displays an error message if the browser is @@ -37,7 +35,7 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given container const graph = new Graph(container); - graph.setEnabled(false); + graph.setEnabled(true); graph.setPanning(true); graph.setTooltips(true); graph.getPlugin('PanningHandler').useLeftButtonForPanning = true; @@ -69,13 +67,13 @@ const Template = ({ label, ...args }) => { // Creates a layout algorithm to be used // with the graph - const layout = new MxFastOrganicLayout(graph); + const layout = new FastOrganicLayout(graph); // Moves stuff wider apart than usual layout.forceConstant = 140; // Adds a button to execute the layout - this.el2.appendChild( + div.appendChild( button('Arrange', function (evt) { const parent = graph.getDefaultParent(); layout.execute(parent); @@ -104,7 +102,7 @@ const Template = ({ label, ...args }) => { if ( this.isEnabled() && - !InternalEvent.isConsumed(evt) && + !isConsumed(evt) && !mxe.isConsumed() && cell != null ) { @@ -112,7 +110,7 @@ const Template = ({ label, ...args }) => { } }; } - } + // Custom parser for simple file format function parse(graph, filename) { @@ -156,7 +154,8 @@ const Template = ({ label, ...args }) => { // Uses the special 2-way style for 2-way labels if (value.indexOf('2-Way') >= 0) { - e.style = '2way'; + const style = + graph.getDataModel().setStyle(e, {baseStyleName:'2way'}); } } } diff --git a/packages/html/stories/FixedPoints.stories.js b/packages/html/stories/FixedPoints.stories.js index 63dbbfb00a..9ee9184ada 100644 --- a/packages/html/stories/FixedPoints.stories.js +++ b/packages/html/stories/FixedPoints.stories.js @@ -6,12 +6,22 @@ import { ConstraintHandler, Point, CellState, - EdgeHandler, + ElbowEdgeHandler, + Client } from '@maxgraph/core'; +import SelectionCellsHandler from '../../core/src/view/handler/SelectionCellsHandler'; +import SelectionHandler from '../../core/src/view/handler/SelectionHandler'; +import PanningHandler from '../../core/src/view/handler/PanningHandler'; +import PopupMenuHandler from '../../core/src/view/handler/PopupMenuHandler'; +import CellEditorHandler from '../../core/src/view/handler/CellEditorHandler'; +import TooltipHandler from '../../core/src/view/handler/TooltipHandler'; + import { globalTypes } from '../.storybook/preview'; import { intersects } from '@maxgraph/core/util/mathUtils'; + + export default { title: 'Connections/FixedPoints', argTypes: { @@ -30,7 +40,11 @@ const Template = ({ label, ...args }) => { container.style.width = `${args.width}px`; container.style.height = `${args.height}px`; container.style.background = 'url(/images/grid.gif)'; - container.style.cursor = 'default'; + container.style.cursor = 'default'; + + Client.imageBasePath = '../../../images' + + class MyCustomConstraintHandler extends ConstraintHandler { // Snaps to fixed points @@ -77,7 +91,7 @@ const Template = ({ label, ...args }) => { } // In case the edge style must be changed during the preview: - // this.edgeState.style.edgeStyle = 'orthogonalEdgeStyle'; + //this.edgeState.style.edgeStyle = 'orthogonalEdgeStyle'; // And to use the new edge style in the new edge inserted into the graph, // update the cell style as follows: // this.edgeState.cell.style = utils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style.edgeStyle); @@ -95,19 +109,29 @@ const Template = ({ label, ...args }) => { } } - class MyCustomEdgeHandler extends EdgeHandler { + class MyCustomEdgeHandler extends ElbowEdgeHandler { // Disables floating connections (only use with no connect image) isConnectableCell(cell) { return graph.getPlugin('ConnectionHandler').isConnectableCell(cell); } } + const plugins = [ + CellEditorHandler, + TooltipHandler, + SelectionCellsHandler, + PopupMenuHandler, + MyCustomConnectionHandler, + SelectionHandler, + PanningHandler, + ]; + class MyCustomGraph extends Graph { - createConnectionHandler() { - const r = new MyCustomConnectionHandler(); - r.constraintHandler = new MyCustomConstraintHandler(this); - return r; - } + // createConnectionHandler() { + // const r = new MyCustomConnectionHandler(); + // r.constraintHandler = new MyCustomConstraintHandler(this); + // return r; + // } createEdgeHandler(state, edgeStyle) { const r = new MyCustomEdgeHandler(state, edgeStyle); @@ -133,8 +157,10 @@ const Template = ({ label, ...args }) => { } // Creates the graph inside the given container - const graph = new MyCustomGraph(container); + const graph = new MyCustomGraph(container, null, plugins); graph.setConnectable(true); + + // graph.getPlugin('ConnectionHandler').constraintHandler = new MyCustomConstraintHandler(this); // Enables rubberband selection if (args.rubberBand) new RubberBandHandler(graph); @@ -179,6 +205,7 @@ const Template = ({ label, ...args }) => { entryX: 0, entryY: 0, entryPerimeter: 1, + bendable: true }, }); const e2 = graph.insertEdge({ @@ -193,6 +220,7 @@ const Template = ({ label, ...args }) => { entryX: 0, entryY: 0, entryPerimeter: 1, + bendable: true }, }); }); diff --git a/packages/html/stories/Folding.stories.js b/packages/html/stories/Folding.stories.js index f730ab4898..fa549c91f2 100644 --- a/packages/html/stories/Folding.stories.js +++ b/packages/html/stories/Folding.stories.js @@ -1,4 +1,5 @@ import { Graph, constants, EdgeStyle, StackLayout, LayoutManager } from '@maxgraph/core'; +import { skipPartiallyEmittedExpressions } from 'typescript'; import { globalTypes } from '../.storybook/preview'; @@ -27,22 +28,27 @@ const Template = ({ label, ...args }) => { graph.setDropEnabled(true); // Disables global features - graph.collapseToPreferredSize = false; + graph.options.collapseToPreferredSize = false; graph.constrainChildren = false; graph.cellsSelectable = false; - graph.extendParentsOnAdd = false; + graph.extendParentsOnAdd = true; graph.extendParents = false; graph.border = 10; // Sets global styles let style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.EntityRelation; - style.rounded = true; + style.edgeStyle = EdgeStyle.EntityRelation; + style.rounded=true; + style = graph.getStylesheet().getDefaultVertexStyle(); style.fillColor = '#ffffff'; style.shape = 'swimlane'; style.startSize = 30; + style.foldable=true; + + + style = []; style.shape = constants.SHAPE_RECTANGLE; diff --git a/packages/html/stories/Groups.stories.js b/packages/html/stories/Groups.stories.js index e77b488da3..82f5cf6746 100644 --- a/packages/html/stories/Groups.stories.js +++ b/packages/html/stories/Groups.stories.js @@ -42,7 +42,7 @@ const Template = ({ label, ...args }) => { SelectionHandler.prototype.getInitialCellForEvent; SelectionHandler.prototype.getInitialCellForEvent = function (me) { const model = this.graph.getDataModel(); - const psel = this.graph.getSelectionCell().getParent(); + const psel = this.graph.getSelectionCell()?.getParent() ||null; let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments); let parent = cell.getParent(); @@ -66,7 +66,7 @@ const Template = ({ label, ...args }) => { SelectionHandler.prototype.isDelayedSelection = function (cell) { let result = graphHandlerIsDelayedSelection.apply(this, arguments); const model = this.graph.getDataModel(); - const psel = this.graph.getSelectionCell().getParent(); + const psel = this.graph.getSelectionCell()?.getParent() || null; const parent = cell.getParent(); if (psel == null || (psel != cell && psel != parent)) { diff --git a/packages/html/stories/Guides.stories.js b/packages/html/stories/Guides.stories.js index 5d8c6da2da..57c4b9a041 100644 --- a/packages/html/stories/Guides.stories.js +++ b/packages/html/stories/Guides.stories.js @@ -2,11 +2,15 @@ import { Graph, SelectionHandler, InternalEvent, + constants, EdgeHandler, EdgeStyle, + KeyHandler, RubberBandHandler, } from '@maxgraph/core'; +import {isAltDown} from '../../core/src/util/EventUtils' +import { brotliDecompressSync } from 'zlib'; import { globalTypes } from '../.storybook/preview'; @@ -14,10 +18,10 @@ export default { title: 'Misc/Guides', argTypes: { ...globalTypes, - rubberBand: { - type: 'boolean', - defaultValue: true, - }, + //rubberBand: { + // type: 'boolean', + // defaultValue: true, + //}, }, }; @@ -35,14 +39,14 @@ const Template = ({ label, ...args }) => { // Alt disables guides SelectionHandler.prototype.useGuidesForEvent = function (me) { - return !InternalEvent.isAltDown(me.getEvent()); + return !isAltDown(me.getEvent()); }; // Defines the guides to be red (default) - // constants.GUIDE_COLOR = '#FF0000'; + ////constants.GUIDE_COLOR = '#FF0000'; // Defines the guides to be 1 pixel (default) - // constants.GUIDE_STROKEWIDTH = 1; + //constants.GUIDE_STROKEWIDTH = 1; // Enables snapping waypoints to terminals EdgeHandler.prototype.snapToTerminals = true; @@ -50,8 +54,7 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given container const graph = new Graph(container); graph.setConnectable(true); - graph.gridSize = 30; - + graph.gridSize = 10; // Changes the default style for edges "in-place" and assigns // an alternate edge style which is applied in Graph.flip // when the user double clicks on the adjustment control point @@ -59,7 +62,8 @@ const Template = ({ label, ...args }) => { // if the horizontal style is true. const style = graph.getStylesheet().getDefaultEdgeStyle(); style.rounded = true; - style.edge = EdgeStyle.ElbowConnector; + style.bendable = true; + style.edgeStyle = EdgeStyle.ElbowConnector; graph.alternateEdgeStyle = 'elbow=vertical'; // Enables rubberband selection @@ -79,6 +83,7 @@ const Template = ({ label, ...args }) => { // Handles cursor keys const nudge = function (keyCode) { + if (!graph.isSelectionEmpty()) { let dx = 0; let dy = 0; @@ -95,13 +100,14 @@ const Template = ({ label, ...args }) => { graph.moveCells(graph.getSelectionCells(), dx, dy); } + } // Transfer initial focus to graph container for keystroke handling graph.container.focus(); // Handles keystroke events - const keyHandler = new KeyHandler(graph); - + const keyHandler = new KeyHandler(graph); + // Ignores enter keystroke. Remove this line if you want the // enter keystroke to stop editing keyHandler.enter = function () {}; @@ -121,7 +127,6 @@ const Template = ({ label, ...args }) => { keyHandler.bindKey(40, function () { nudge(40); }); - }; return container; }; diff --git a/packages/html/stories/Handles.stories.js b/packages/html/stories/Handles.stories.js index 81df8b432e..101406fd4c 100644 --- a/packages/html/stories/Handles.stories.js +++ b/packages/html/stories/Handles.stories.js @@ -80,7 +80,7 @@ const Template = ({ label, ...args }) => { class MyCustomVertexHandler extends VertexHandler { livePreview = true; - + rotationEnabled = true; createCustomHandles() { diff --git a/packages/html/stories/HelloPort.stories.js b/packages/html/stories/HelloPort.stories.js index baca48dee4..5053caac27 100644 --- a/packages/html/stories/HelloPort.stories.js +++ b/packages/html/stories/HelloPort.stories.js @@ -6,6 +6,7 @@ import { constants, DomHelpers, Client, + Codec } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -44,7 +45,8 @@ const Template = ({ label, ...args }) => { // Sets the default edge style const style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; + style.bendable=true // Ports are not used as terminals for edges, they are // only used to compute the graphical connection point diff --git a/packages/html/stories/HoverIcons.stories.js b/packages/html/stories/HoverIcons.stories.js index 6cb534f017..ea3821cda8 100644 --- a/packages/html/stories/HoverIcons.stories.js +++ b/packages/html/stories/HoverIcons.stories.js @@ -32,9 +32,6 @@ const Template = ({ label, ...args }) => { container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; - // Defines an icon for creating new connections in the connection handler. - // This will automatically disable the highlighting of the source vertex. - ConnectionHandler.prototype.connectImage = new ImageBox('images/connector.gif', 16, 16); // Defines a new class for all icons class mxIconSet { @@ -103,6 +100,11 @@ const Template = ({ label, ...args }) => { // Creates the graph inside the given container const graph = new Graph(container); + // Defines an icon for creating new connections in the connection handler. + // This will automatically disable the highlighting of the source vertex. + + const connectionHandler = graph.getPlugin('ConnectionHandler'); + connectionHandler.connectImage = new ImageBox('images/connector.gif', 16, 16); graph.setConnectable(true); // Enables rubberband selection diff --git a/packages/html/stories/Images.stories.js b/packages/html/stories/Images.stories.js index 6196fb0ac8..f7ec37e802 100644 --- a/packages/html/stories/Images.stories.js +++ b/packages/html/stories/Images.stories.js @@ -94,8 +94,8 @@ const Template = ({ label, ...args }) => { function configureStylesheet(graph) { let style = {}; style.shape = constants.SHAPE.IMAGE; - style.perimiter = Perimeter.RectanglePerimeter; - style.image = 'images/icons48/keys.png'; + style.perimeter = Perimeter.RectanglePerimeter; + style.image = 'images/keys.png'; style.fontColor = '#FFFFFF'; graph.getStylesheet().putCellStyle('image', style); @@ -106,16 +106,16 @@ const Template = ({ label, ...args }) => { style.verticalAlign = constants.ALIGN.TOP; style.imageAlign = constants.ALIGN.CENTER; style.imageVerticalAlign = constants.ALIGN.TOP; - style.image = 'images/icons48/gear.png'; - style.imageWidth = '48'; - style.imageHeight = '48'; - style.spacingTop = '56'; - style.spacing = '8'; + style.image = 'images/gear.png'; + style.imageWidth = 48; + style.imageHeight = 48; + style.spacingTop = 56; + style.spacing = 8; graph.getStylesheet().putCellStyle('bottom', style); style = cloneUtils.clone(style); style.imageVerticalAlign = constants.ALIGN.BOTTOM; - style.image = 'images/icons48/server.png'; + style.image = 'images/server.png'; delete style.spacingTop; graph.getStylesheet().putCellStyle('top', style); @@ -124,16 +124,16 @@ const Template = ({ label, ...args }) => { style.imageAlign = constants.ALIGN.LEFT; style.verticalAlign = constants.ALIGN.MIDDLE; style.imageVerticalAlign = constants.ALIGN.MIDDLE; - style.image = 'images/icons48/earth.png'; - style.spacingLeft = '55'; - style.spacing = '4'; + style.image = 'images/earth.png'; + style.spacingLeft = 55; + style.spacing = 4; graph.getStylesheet().putCellStyle('right', style); style = cloneUtils.clone(style); style.align = constants.ALIGN.RIGHT; style.imageAlign = constants.ALIGN.RIGHT; delete style.spacingLeft; - style.spacingRight = '55'; + style.spacingRight = 55; graph.getStylesheet().putCellStyle('left', style); } diff --git a/packages/html/stories/Indicators.stories.js b/packages/html/stories/Indicators.stories.js index c96f1866c9..da0859b4ab 100644 --- a/packages/html/stories/Indicators.stories.js +++ b/packages/html/stories/Indicators.stories.js @@ -15,8 +15,7 @@ const Template = ({ label, ...args }) => { 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'; + // Creates the graph inside the given container const graph = new Graph(container); @@ -30,6 +29,8 @@ const Template = ({ label, ...args }) => { let style = graph.getStylesheet().getDefaultVertexStyle(); style.shape = 'label'; + style.fillColor= 'none'; + style.strokeColor= 'none'; style.verticalAlign = 'bottom'; style.indicatorShape = 'ellipse'; style.indicatorWidth = 34; @@ -43,9 +44,10 @@ const Template = ({ label, ...args }) => { // Creates a style with an indicator style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; style.elbow = constants.ELBOW.VERTICAL; style.rounded = true; + style.bendable = true; // Gets the default parent for inserting new cells. This // is normally the first child of the root (ie. layer 0). diff --git a/packages/html/stories/Labels.stories.js b/packages/html/stories/Labels.stories.js index e397faf791..1670ef0915 100644 --- a/packages/html/stories/Labels.stories.js +++ b/packages/html/stories/Labels.stories.js @@ -100,10 +100,12 @@ const Template = ({ label, ...args }) => { // 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 style = graph.getStylesheet().getDefaultVertexStyle(); + style.foldable=true; // Adds cells to the model in a single step graph.batchUpdate(() => { const v1 = graph.insertVertex(parent, null, 'vertexLabelsMovable', 20, 20, 80, 30); + // Places sublabels inside the vertex const label11 = graph.insertVertex( diff --git a/packages/html/stories/Markers.stories.js b/packages/html/stories/Markers.stories.js index 1eadac7428..8449094af5 100644 --- a/packages/html/stories/Markers.stories.js +++ b/packages/html/stories/Markers.stories.js @@ -24,7 +24,6 @@ const Template = ({ label, ...args }) => { 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'; // Enables guides @@ -125,8 +124,8 @@ const Template = ({ label, ...args }) => { style.fontColor = '#000000'; style.fontStyle = '0'; style.fontStyle = '0'; - style.startSize = '8'; - style.endSize = '8'; + style.startSize = 8; + style.endSize = 8; // Populates the graph const parent = graph.getDefaultParent(); @@ -161,6 +160,7 @@ const Template = ({ label, ...args }) => { startSize: 12, endArrow: 'block', labelBackgroundColor: '#FFFFFF', + endFill: 1 }); const v5 = graph.insertVertex(parent, null, 'v5', 40, 220, 40, 40, { diff --git a/packages/html/stories/Monitor.stories.js b/packages/html/stories/Monitor.stories.js index 0141d44547..6c1d086c73 100644 --- a/packages/html/stories/Monitor.stories.js +++ b/packages/html/stories/Monitor.stories.js @@ -1,6 +1,7 @@ import { Graph, EdgeStyle, + InternalEvent, DomHelpers, xmlUtils, Perimeter, @@ -8,6 +9,7 @@ import { constants, cloneUtils, Codec, + CellOverlay } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -27,7 +29,6 @@ const Template = ({ label, ...args }) => { 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); @@ -39,7 +40,7 @@ const Template = ({ label, ...args }) => { // Creates a process display using the activity names as IDs to refer to the elements const xml = - '' + + '' + '' + '' + '' + @@ -76,10 +77,10 @@ const Template = ({ label, ...args }) => { '' + '' + '' + - ''; + ''; const doc = xmlUtils.parseXml(xml); const codec = new Codec(doc); - codec.decode(doc.documentElement, graph.getDataModel()); + codec.decode(doc, graph.getDataModel()); const buttons = document.createElement('div'); div.appendChild(buttons); @@ -104,9 +105,9 @@ const Template = ({ label, ...args }) => { if (xml != null && xml.length > 0) { const doc = xmlUtils.parseXml(xml); - if (doc != null && doc.documentElement != null) { + if (doc != null ) { const model = graph.getDataModel(); - const nodes = doc.documentElement.getElementsByTagName('update'); + const nodes = doc.getElementsByTagName('update'); if (nodes != null && nodes.length > 0) { model.beginUpdate(); @@ -194,10 +195,11 @@ const Template = ({ label, ...args }) => { style.fontStyle = 1; style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; style.strokeColor = '#808080'; style.rounded = true; style.shadow = true; + style.endFill=1; style = []; style.shape = constants.SHAPE.SWIMLANE; diff --git a/packages/html/stories/OrgChart.stories.js b/packages/html/stories/OrgChart.stories.js index 353fefbb2b..55182c7b46 100644 --- a/packages/html/stories/OrgChart.stories.js +++ b/packages/html/stories/OrgChart.stories.js @@ -11,10 +11,13 @@ import { LayoutManager, CellOverlay, ImageBox, - utils, MaxToolbar, + MaxWindow, + PrintPreview } from '@maxgraph/core'; +import {getScaleForPageCount}from '../../core/src/util/printUtils' + import { globalTypes } from '../.storybook/preview'; export default { @@ -30,21 +33,23 @@ export default { const Template = ({ label, ...args }) => { const div = document.createElement('div'); - + const outlineCont = document.createElement('div'); + outlineCont.style="z-index:1;position:absolute;overflow:hidden;top:0px;right:0px;width:160px;height:120px;background:transparent;border-style:solid;border-color:lightgray;" 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); + div.appendChild(outlineCont); + Client.imageBasePath = '/images' // Should we allow overriding constants? // Makes the shadow brighter //constants.SHADOWCOLOR = '#C0C0C0'; - const outline = document.getElementById('outlineContainer'); + if (!args.contextMenu) InternalEvent.disableContextMenu(container); @@ -75,10 +80,9 @@ const Template = ({ label, ...args }) => { // do not select the cell when the popup menu // is displayed panningHandler.popupMenuHandler = false; - // Creates the outline (navigator, overview) for moving // around the graph in the top, right corner of the window. - const outln = new Outline(graph, outline); + const outln = new Outline(graph, outlineCont); // Disables tooltips on touch devices graph.setTooltips(!Client.IS_TOUCH); @@ -86,6 +90,7 @@ const Template = ({ label, ...args }) => { // Set some stylesheet options for the visual appearance of vertices let style = graph.getStylesheet().getDefaultVertexStyle(); style.shape = 'label'; + style.editable=true style.verticalAlign = constants.ALIGN.MIDDLE; style.align = constants.ALIGN.LEFT; @@ -97,7 +102,7 @@ const Template = ({ label, ...args }) => { style.fontColor = '#1d258f'; style.fontFamily = 'Verdana'; - style.fontSize = '12'; + style.fontSize = 12; style.fontStyle = '1'; style.shadow = '1'; @@ -105,8 +110,8 @@ const Template = ({ label, ...args }) => { style.glass = '1'; style.image = '/images/dude3.png'; - style.imageWidth = '48'; - style.imageHeight = '48'; + style.imageWidth = 48; + style.imageHeight = 48; style.spacing = 8; // Sets the default style for edges @@ -121,7 +126,7 @@ const Template = ({ label, ...args }) => { style.entryPerimeter = 0; // disabled // Disable the following for straight lines - style.edge = EdgeStyle.TopToBottom; + style.edgeStyle = EdgeStyle.TopToBottom; // Stops editing on enter or escape keypress const keyHandler = new KeyHandler(graph); @@ -202,7 +207,7 @@ const Template = ({ label, ...args }) => { parent, 'treeRoot', 'Organization', - w / 2 - 30, + w, 20, 140, 60, @@ -214,7 +219,7 @@ const Template = ({ label, ...args }) => { const content = document.createElement('div'); content.style.padding = '4px'; - div.appendChild(content); + const tb = new MaxToolbar(content); tb.addItem('Zoom In', 'images/zoom_in32.png', function (evt) { @@ -235,18 +240,22 @@ const Template = ({ label, ...args }) => { }); tb.addItem('Poster Print', 'images/press32.png', function (evt) { - const pageCount = utils.prompt('Enter maximum page count', '1'); + const pageCount = prompt('Enter maximum page count', '1'); if (pageCount != null) { - const scale = utils.getScaleForPageCount(pageCount, graph); + const scale = getScaleForPageCount(pageCount, graph); const preview = new PrintPreview(graph, scale); preview.open(); } }); + const wnd = new MaxWindow('Tools', content, 0, 0, 200, 66, false); + wnd.setMaximizable(false); + wnd.setScrollable(false); + wnd.setResizable(false); + wnd.setVisible(true); // Function to create the entries in the popupmenu function createPopupMenu(graph, menu, cell, evt) { - const model = graph.getDataModel(); if (cell != null) { if (cell.isVertex()) { @@ -355,9 +364,10 @@ const Template = ({ label, ...args }) => { } function deleteSubtree(graph, cell) { + // Gets the subtree from cell downwards const cells = []; - graph.traverse(cell, true, function (vertex) { + layout.traverse(cell, true, function (vertex) { cells.push(vertex); return true; diff --git a/packages/html/stories/Orthogonal.stories.js b/packages/html/stories/Orthogonal.stories.js index 3fbdd234fa..ebde3bf7c3 100644 --- a/packages/html/stories/Orthogonal.stories.js +++ b/packages/html/stories/Orthogonal.stories.js @@ -67,8 +67,10 @@ const Template = ({ label, ...args }) => { }; // Changes the default edge style - graph.getStylesheet().getDefaultEdgeStyle().edgeStyle = 'orthogonalEdgeStyle'; - delete graph.getStylesheet().getDefaultEdgeStyle().endArrow; + const style = graph.getStylesheet().getDefaultEdgeStyle(); + style.edgeStyle = 'orthogonalEdgeStyle' + delete style.endArrow; + style.bendable=true const connectionHandler = graph.getPlugin('ConnectionHandler'); diff --git a/packages/html/stories/Overlays.stories.js b/packages/html/stories/Overlays.stories.js index a7579024d9..32f466238a 100644 --- a/packages/html/stories/Overlays.stories.js +++ b/packages/html/stories/Overlays.stories.js @@ -45,7 +45,7 @@ const Template = ({ label, ...args }) => { if (cell != null) { const overlays = graph.getCellOverlays(cell); - if (overlays == null) { + if (overlays.length==0) { // Creates a new overlay with an image and a tooltip const overlay = new CellOverlay( new ImageBox('/images/check.png', 16, 16), @@ -54,7 +54,7 @@ const Template = ({ label, ...args }) => { // Installs a handler for clicks on the overlay overlay.addListener(InternalEvent.CLICK, (sender, evt2) => { - utils.alert('Overlay clicked'); + alert('Overlay clicked'); }); // Sets the overlay for the cell in the graph diff --git a/packages/html/stories/PageBreaks.stories.js b/packages/html/stories/PageBreaks.stories.js index 393c809a9b..5e3b25bed6 100644 --- a/packages/html/stories/PageBreaks.stories.js +++ b/packages/html/stories/PageBreaks.stories.js @@ -4,8 +4,11 @@ import { RubberBandHandler, DomHelpers, InternalEvent, + PrintPreview } from '@maxgraph/core'; +import { write } from '../../core/src/util/domUtils'; + import { globalTypes } from '../.storybook/preview'; export default { diff --git a/packages/html/stories/Perimeter.stories.js b/packages/html/stories/Perimeter.stories.js index 889f370ab1..dd7b7fb0f6 100644 --- a/packages/html/stories/Perimeter.stories.js +++ b/packages/html/stories/Perimeter.stories.js @@ -1,5 +1,7 @@ import { Graph, RubberBandHandler, GraphView, mathUtils } from '@maxgraph/core'; + + import { globalTypes } from '../.storybook/preview'; export default { diff --git a/packages/html/stories/Permissions.stories.js b/packages/html/stories/Permissions.stories.js index a2ccd77f5f..23cf581de9 100644 --- a/packages/html/stories/Permissions.stories.js +++ b/packages/html/stories/Permissions.stories.js @@ -32,13 +32,13 @@ const Template = ({ label, ...args }) => { container.style.cursor = 'default'; div.appendChild(container); - // Defines an icon for creating new connections in the connection handler. - // This will automatically disable the highlighting of the source vertex. - ConnectionHandler.prototype.connectImage = new ImageBox('images/connector.gif', 16, 16); // Creates the graph inside the given container const graph = new Graph(container); + const connectionHandler = graph.getPlugin('ConnectionHandler'); + connectionHandler.connectImage = new ImageBox('images/connector.gif', 16, 16); + // Enable tooltips, disables mutligraphs, enable loops graph.setMultigraph(false); graph.setAllowLoops(true); diff --git a/packages/html/stories/PortRefs.stories.js b/packages/html/stories/PortRefs.stories.js index 68d5bcc29e..19e3eb3552 100644 --- a/packages/html/stories/PortRefs.stories.js +++ b/packages/html/stories/PortRefs.stories.js @@ -12,6 +12,7 @@ import { Client, } from '@maxgraph/core'; + import { globalTypes } from '../.storybook/preview'; export default { @@ -33,8 +34,6 @@ const Template = ({ label, ...args }) => { container.style.cursor = 'default'; // Replaces the port image - ConstraintHandler.prototype.pointImage = new ImageBox('/images/dot.gif', 10, 10); - const graph = new Graph(container); graph.setConnectable(true); @@ -63,19 +62,28 @@ const Template = ({ label, ...args }) => { ports.sw = { x: 0, y: 1, perimeter: true, constraint: 'south west' }; ports.se = { x: 1, y: 1, perimeter: true, constraint: 'south east' }; + /*ports.w = {x: 0, y: 0.5, perimeter: true, constraint: 'west'}; + ports.e = {x: 1, y: 0.5, perimeter: true, constraint: 'east'}; + ports.n = {x: 0.5, y: 0, perimeter: true, constraint: 'north'}; + ports.s = {x: 0.5, y: 1, perimeter: true, constraint: 'south'}; + ports.nw = {x: 0, y: 0, perimeter: true, constraint: 'north west'}; + ports.ne = {x: 1, y: 0, perimeter: true, constraint: 'north east'}; + ports.sw= {x: 0, y: 1, perimeter: true, constraint: 'south west'}; + ports.se = {x: 1, y: 1, perimeter: true, constraint: 'south east'}; +*/ // ... except for triangles const ports2 = new Array(); // NOTE: Constraint is used later for orthogonal edge routing (currently ignored) ports2.in1 = { x: 0, y: 0, perimeter: true, constraint: 'west' }; - ports2.in2 = { x: 0, y: 0.25, perimeter: true, constraint: 'west' }; - ports2.in3 = { x: 0, y: 0.5, perimeter: true, constraint: 'west' }; - ports2.in4 = { x: 0, y: 0.75, perimeter: true, constraint: 'west' }; - ports2.in5 = { x: 0, y: 1, perimeter: true, constraint: 'west' }; + ports2.in2 = { x: 0.25, y: 0, perimeter: true, constraint: 'west' }; + ports2.in3 = { x: 0.5, y: 0, perimeter: true, constraint: 'west' }; + ports2.in4 = { x: 0.75, y: 0, perimeter: true, constraint: 'west' }; + ports2.in5 = { x: 1, y: 0, perimeter: true, constraint: 'west' }; ports2.out1 = { - x: 0.5, - y: 0, + x: 0, + y: 0.5, perimeter: true, constraint: 'north east', }; @@ -86,7 +94,17 @@ const Template = ({ label, ...args }) => { perimeter: true, constraint: 'south east', }; - + /* + ports2.in1 = {x: 0, y: 0, perimeter: true, constraint: 'west'}; + ports2.in2 = {x: 0, y: 0.25, perimeter: true, constraint: 'west'}; + ports2.in3 = {x: 0, y: 0.5, perimeter: true, constraint: 'west'}; + ports2.in4 = {x: 0, y: 0.75, perimeter: true, constraint: 'west'}; + ports2.in5 = {x: 0, y: 1, perimeter: true, constraint: 'west'}; + + ports2.out1 = {x: 0.5, y: 0, perimeter: true, constraint: 'north east'}; + ports2.out2 = {x: 1, y: 0.5, perimeter: true, constraint: 'east'}; + ports2.out3 = {x: 0.5, y: 1, perimeter: true, constraint: 'south east'}; +*/ // Extends shapes classes to return their ports Shape.prototype.getPorts = function () { return ports; @@ -97,7 +115,7 @@ const Template = ({ label, ...args }) => { }; const connectionHandler = graph.getPlugin('ConnectionHandler'); - + connectionHandler.constraintHandler.pointImage=new ImageBox('/images/dot.gif', 10, 10); // Disables floating connections (only connections via ports allowed) connectionHandler.isConnectableCell = function (cell) { return false; @@ -160,7 +178,7 @@ const Template = ({ label, ...args }) => { const id = edge.style[key]; if (id != null) { - const c = new ConnectionConstraint(null, null); + const c = new ConnectionConstraint(null); c.id = id; return c; @@ -176,7 +194,7 @@ const Template = ({ label, ...args }) => { const port = vertex.shape.getPorts()[constraint.id]; if (port != null) { - constraint = new ConnectionConstraint(new Point(port.x, port.y), port.perimeter); + arguments[1] = new ConnectionConstraint(new Point(port.x, port.y), port.perimeter); } } diff --git a/packages/html/stories/SecondLabel.stories.js b/packages/html/stories/SecondLabel.stories.js index e2d978b116..04ce34bbea 100644 --- a/packages/html/stories/SecondLabel.stories.js +++ b/packages/html/stories/SecondLabel.stories.js @@ -74,16 +74,17 @@ const Template = ({ label, ...args }) => { 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 + !this.isVertex() || + this.geometry == null || + !this.geometry.relative || + this.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) { @@ -163,6 +164,7 @@ const Template = ({ label, ...args }) => { // 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. + v1.isVisible=isVisible const v11 = graph.insertVertex( v1, null, @@ -179,6 +181,7 @@ const Template = ({ label, ...args }) => { }, true ); + v11.isVisible=isVisible v11.geometry.offset = new Point(-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 @@ -203,6 +206,7 @@ const Template = ({ label, ...args }) => { true ); v21.geometry.offset = new Point(-8, -8); + v21.isVisible=isVisible graph.updateCellSize(v21); const e1 = graph.insertEdge(parent, null, '', v1, v2); }); diff --git a/packages/html/stories/Stencils.stories.js b/packages/html/stories/Stencils.stories.js index b765f737b0..14f66da60a 100644 --- a/packages/html/stories/Stencils.stories.js +++ b/packages/html/stories/Stencils.stories.js @@ -13,7 +13,6 @@ import { StencilShape, StencilShapeRegistry, CellRenderer, - utils, load, } from '@maxgraph/core'; @@ -156,7 +155,7 @@ const Template = ({ label, ...args }) => { // Changes default styles let style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = 'orthogonalEdgeStyle'; + style.edgeStyle = 'orthogonalEdgeStyle'; style = graph.getStylesheet().getDefaultVertexStyle(); style.fillColor = '#adc5ff'; style.gradientColor = '#7d85df'; @@ -302,10 +301,13 @@ const Template = ({ label, ...args }) => { const cell = graph.getSelectionCell(); if (cell != null) { - const style = utils.prompt('Style', cell.getStyle()); - + let style = cell.getStyle(); + let sstyle= JSON.stringify(style) + let pstyle = prompt('Style', sstyle) +let rstyle=JSON.parse(pstyle) + if (style != null) { - graph.getDataModel().setStyle(cell, style); + graph.getDataModel().setStyle(cell, rstyle); } } }) diff --git a/packages/html/stories/Stylesheet.stories.js b/packages/html/stories/Stylesheet.stories.js index b30f7c3dc8..8dd44ae792 100644 --- a/packages/html/stories/Stylesheet.stories.js +++ b/packages/html/stories/Stylesheet.stories.js @@ -28,20 +28,20 @@ const Template = ({ label, ...args }) => { // a supercall to use the default implementation. graph.getLabel = function (cell) { const label = Graph.prototype.getLabel.apply(this, arguments); - if (cell.isEdge()) { return `Transfer ${label}`; } return label; + }; // Installs a custom global tooltip graph.setTooltips(true); graph.getTooltip = function (state) { const { cell } = state; - const model = this.getDataModel(); + // const model = this.getDataModel(); - if (modcellel.isEdge()) { + if (cell.isEdge()) { const source = this.getLabel(cell.getTerminal(true)); const target = this.getLabel(cell.getTerminal(false)); @@ -53,7 +53,7 @@ const Template = ({ label, ...args }) => { // Creates the default style for vertices let style = []; style.shape = constants.SHAPE.RECTANGLE; - style.perimiter = Perimeter.RectanglePerimeter; + style.perimeter = Perimeter.RectanglePerimeter; style.strokeColor = 'gray'; style.rounded = true; style.fillColor = '#EEEEEE'; @@ -61,7 +61,7 @@ const Template = ({ label, ...args }) => { style.fontColor = '#774400'; style.align = constants.ALIGN.CENTER; style.verticalAlign = constants.ALIGN.MIDDLE; - style.fontSize = '12'; + style.fontSize = 12; style.fontStyle = 1; graph.getStylesheet().putDefaultVertexStyle(style); @@ -71,9 +71,9 @@ const Template = ({ label, ...args }) => { style.strokeColor = '#6482B9'; style.align = constants.ALIGN.CENTER; style.verticalAlign = constants.ALIGN.MIDDLE; - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; style.endArrow = constants.ARROW.CLASSIC; - style.fontSize = '10'; + style.fontSize = 10; graph.getStylesheet().putDefaultEdgeStyle(style); // Gets the default parent for inserting new cells. This @@ -82,7 +82,7 @@ const Template = ({ label, ...args }) => { // Adds cells to the model in a single step graph.batchUpdate(() => { - const v1 = graph.insertVertex(parent, null, 'Interval 1', 20, 20, 180, 30); + const v1 = graph.insertVertex({parent, value:'Interval 1', position:[20, 20], size:[180, 30]}); const v2 = graph.insertVertex(parent, null, 'Interval 2', 140, 80, 280, 30); const v3 = graph.insertVertex(parent, null, 'Interval 3', 200, 140, 360, 30); const v4 = graph.insertVertex(parent, null, 'Interval 4', 480, 200, 120, 30); diff --git a/packages/html/stories/SwimLanes.stories.js b/packages/html/stories/SwimLanes.stories.js index 8ea9c62fee..d64cd9c8f9 100644 --- a/packages/html/stories/SwimLanes.stories.js +++ b/packages/html/stories/SwimLanes.stories.js @@ -1,5 +1,5 @@ import { - Editor, + Graph, ConnectionHandler, ImageBox, Perimeter, @@ -11,6 +11,7 @@ import { SwimlaneManager, StackLayout, LayoutManager, + Client } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -31,6 +32,7 @@ const Template = ({ label, ...args }) => { container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; + // Defines an icon for creating new connections in the connection handler. // This will automatically disable the highlighting of the source vertex. ConnectionHandler.prototype.connectImage = new ImageBox('images/connector.gif', 16, 16); @@ -42,11 +44,11 @@ const Template = ({ label, ...args }) => { // .load('editors/config/keyhandler-commons.xml') // .getDocumentElement(); // const editor = new Editor(config); - const editor = new Editor(null); - editor.setGraphContainer(container); - const { graph } = editor; + //const editor = new Editor(null); + //editor.setGraphContainer(container); + const graph= new Graph(container) const model = graph.getDataModel(); - + // Auto-resizes the container graph.border = 80; graph.getView().translate = new Point(graph.border / 2, graph.border / 2); @@ -59,13 +61,14 @@ const Template = ({ label, ...args }) => { let style = graph.getStylesheet().getDefaultVertexStyle(); style.shape = constants.SHAPE.SWIMLANE; style.verticalAlign = 'middle'; - style.labelBackgroundColor = 'white'; + style.labelBackgroundColor = 'none'; style.fontSize = 11; style.startSize = 22; style.horizontal = false; style.fontColor = 'black'; style.strokeColor = 'black'; - // delete style.fillColor; + style.foldable=true + style.fillColor='none'; style = cloneUtils.clone(style); style.shape = constants.SHAPE.RECTANGLE; @@ -74,6 +77,7 @@ const Template = ({ label, ...args }) => { style.horizontal = true; style.verticalAlign = 'middle'; delete style.startSize; + style.foldable=false; style.labelBackgroundColor = 'none'; graph.getStylesheet().putCellStyle('process', style); @@ -81,14 +85,15 @@ const Template = ({ label, ...args }) => { style.shape = constants.SHAPE.ELLIPSE; style.perimiter = Perimeter.EllipsePerimeter; delete style.rounded; + style.foldable=false; graph.getStylesheet().putCellStyle('state', style); - style = cloneUtils.clone(style); style.shape = constants.SHAPE.RHOMBUS; style.perimiter = Perimeter.RhombusPerimeter; style.verticalAlign = 'top'; style.spacingTop = 40; style.spacingRight = 64; + style.foldable=false; graph.getStylesheet().putCellStyle('condition', style); style = cloneUtils.clone(style); @@ -98,12 +103,14 @@ const Template = ({ label, ...args }) => { style.fontSize = 14; style.fontStyle = 1; delete style.spacingRight; + style.foldable=false; graph.getStylesheet().putCellStyle('end', style); style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; style.endArrow = constants.ARROW.BLOCK; style.rounded = true; + style.bendable=true; style.fontColor = 'black'; style.strokeColor = 'black'; @@ -214,8 +221,7 @@ const Template = ({ label, ...args }) => { const getStyle = function () { // TODO super cannot be used here // let style = super.getStyle(); - let style = {}; - + let style = this.style; if (this.isCollapsed()) { style.horizontal = 1; style.align = 'left'; diff --git a/packages/html/stories/Thread.stories.js b/packages/html/stories/Thread.stories.js index 7c32282acd..cf6ed747eb 100644 --- a/packages/html/stories/Thread.stories.js +++ b/packages/html/stories/Thread.stories.js @@ -44,7 +44,7 @@ const Template = ({ label, ...args }) => { const f = () => { const overlays = graph.getCellOverlays(v1); - if (overlays == null) { + if (!overlays.length) { graph.removeCellOverlays(v2); graph.setCellWarning(v1, 'Tooltip'); } else { @@ -53,7 +53,7 @@ const Template = ({ label, ...args }) => { } }; - window.setInterval(f, 1000); + window.setInterval(f, 5000); f(); return container; diff --git a/packages/html/stories/Toolbar.stories.js b/packages/html/stories/Toolbar.stories.js index 4c1bbba062..128dbe0403 100644 --- a/packages/html/stories/Toolbar.stories.js +++ b/packages/html/stories/Toolbar.stories.js @@ -37,23 +37,17 @@ const Template = ({ label, ...args }) => { container.style.height = `${args.height}px`; container.style.background = 'url(/images/grid.gif)'; container.style.cursor = 'default'; + container.style.marginLeft='10px' + container.style.marginTop='10px' div.appendChild(container); - // Defines an icon for creating new connections in the connection handler. - // This will automatically disable the highlighting of the source vertex. - ConnectionHandler.prototype.connectImage = new ImageBox( - '/images/connector.gif', - 16, - 16 - ); - // Creates the div for the toolbar const tbContainer = document.createElement('div'); tbContainer.style.position = 'absolute'; tbContainer.style.overflow = 'hidden'; tbContainer.style.padding = '2px'; tbContainer.style.left = '0px'; - tbContainer.style.top = '0px'; + tbContainer.style.top = '50px'; tbContainer.style.width = '24px'; tbContainer.style.bottom = '0px'; @@ -79,6 +73,10 @@ const Template = ({ label, ...args }) => { }; // Enables new connections in the graph + // Defines an icon for creating new connections in the connection handler. + // This will automatically disable the highlighting of the source vertex. + const connectionHandler = graph.getPlugin('ConnectionHandler'); + connectionHandler.connectImage = new ImageBox('images/connector.gif', 16, 16); graph.setConnectable(true); graph.setMultigraph(false); @@ -129,7 +127,7 @@ const Template = ({ label, ...args }) => { } }); - tbContainer.appendChild(button); + div.insertBefore(button, container); function addToolbarItem(graph, toolbar, prototype, image) { // Function that is executed when the image is dropped on diff --git a/packages/html/stories/Tree.stories.js b/packages/html/stories/Tree.stories.js index 84d89cab98..249d2315f6 100644 --- a/packages/html/stories/Tree.stories.js +++ b/packages/html/stories/Tree.stories.js @@ -13,6 +13,8 @@ import { Point, } from '@maxgraph/core'; +import{traverse} from '../../core/src/util/treeTraversal' + import { globalTypes } from '../.storybook/preview'; export default { @@ -55,10 +57,10 @@ const Template = ({ label, ...args }) => { const { graph } = this.state.view; const hasChildren = graph.getOutgoingEdges(this.state.cell).length > 0; - if (isForeground) { + if (isForeground) { if (hasChildren) { // Painting outside of vertex bounds is used here - path.moveTo(w / 2, h + this.segment); + path.moveTo(w / 2, h + TreeNodeShape.segment); path.lineTo(w / 2, h); path.end(); } @@ -136,18 +138,15 @@ const Template = ({ label, ...args }) => { foldCells(collapse, recurse, cells) { // Implements the click on a folding icon - this.model.beginUpdate(); - try { - this.toggleSubtree(this, cells[0], !collapse); + graph.batchUpdate(()=>{ + this.toggleSubtree(cells[0], !collapse); this.model.setCollapsed(cells[0], collapse); // Executes the layout for the new graph since // changes to visiblity and collapsed state do // not trigger a layout in the current manager. layout.execute(this.getDefaultParent()); - } finally { - this.model.endUpdate(); - } + }) } toggleSubtree(cell, show) { @@ -156,13 +155,13 @@ const Template = ({ label, ...args }) => { show = show != null ? show : true; const cells = []; - this.traverse(cell, true, function (vertex) { + traverse(cell, true, function (vertex) { if (vertex !== cell) { cells.push(vertex); } // Stops recursion if a collapsed cell is seen - return vertex === cell || !this.isCellCollapsed(vertex); + return vertex === cell || !vertex.isCollapsed(); }); this.toggleCells(show, cells, true); @@ -185,7 +184,7 @@ const Template = ({ label, ...args }) => { style.shadow = true; style = graph.getStylesheet().getDefaultEdgeStyle(); - style.edge = EdgeStyle.TopToBottom; + style.edgeStyle = EdgeStyle.TopToBottom; style.rounded = true; // Enables automatic sizing for vertices after editing and diff --git a/packages/html/stories/UserObject.stories.js b/packages/html/stories/UserObject.stories.js index 1a659a3f3f..b837a69977 100644 --- a/packages/html/stories/UserObject.stories.js +++ b/packages/html/stories/UserObject.stories.js @@ -13,6 +13,7 @@ import { MaxForm, CellAttributeChange, } from '@maxgraph/core'; +import { popup } from '@maxgraph/core/gui/MaxWindow'; import { globalTypes } from '../.storybook/preview'; @@ -24,29 +25,21 @@ export default { }; const Template = ({ label, ...args }) => { + const divlayout = document.createElement('div'); const div = document.createElement('div'); - - const table = document.createElement('table'); - table.style.position = 'relative'; - - table.innerHTML = ` - - -
- - -
- - `; - div.appendChild(table); - - const container = document.getElementById('graphContainer'); + div.style.display= 'flex'; + const divtable = document.createElement('div'); + divtable.setAttribute('div', 'divtable') + 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.border = 'solid 1px black'; + container.style.cursor = 'default'; + divlayout.appendChild(div) + div.appendChild(container); + div.appendChild(divtable); // Note that these XML nodes will be enclosing the // Cell nodes for the model cells in the output @@ -122,11 +115,10 @@ const Template = ({ label, ...args }) => { autoSize = true; } - cellLabelChanged.apply(this, arguments); + cellLabelChanged.apply(this, [cell,newValue,autoSize]); }; // Overrides method to create the editing value - const { getEditingValue } = graph; graph.getEditingValue = function (cell) { if (domUtils.isNode(cell.value) && cell.value.nodeName.toLowerCase() == 'person') { const firstName = cell.getAttribute('firstName', ''); @@ -153,14 +145,14 @@ const Template = ({ label, ...args }) => { if (args.rubberBand) new RubberBandHandler(graph); const buttons = document.createElement('div'); - div.appendChild(buttons); + divlayout.appendChild(buttons); // Adds an option to view the XML of the graph buttons.appendChild( DomHelpers.button('View XML', function () { const encoder = new Codec(); const node = encoder.encode(graph.getDataModel()); - popup(utils.getPrettyXml(node), true); + popup(xmlUtils.getPrettyXml(node), true); }) ); @@ -173,17 +165,18 @@ const Template = ({ label, ...args }) => { style.fillColor = '#DFDFDF'; style.gradientColor = 'white'; style.fontColor = 'black'; - style.fontSize = '12'; + style.fontSize = 12; style.spacing = 4; // Creates the default style for edges style = graph.getStylesheet().getDefaultEdgeStyle(); style.strokeColor = '#0C0C0C'; style.labelBackgroundColor = 'white'; - style.edge = EdgeStyle.ElbowConnector; + style.edgeStyle = EdgeStyle.ElbowConnector; + style.bendable=true; style.rounded = true; style.fontColor = 'black'; - style.fontSize = '10'; + style.fontSize = 10; // Gets the default parent for inserting new cells. This // is normally the first child of the root (ie. layer 0). @@ -208,25 +201,25 @@ const Template = ({ label, ...args }) => { * Updates the properties panel */ function selectionChanged(graph) { - const div = document.getElementById('properties'); + //const div = document.getElementById('properties'); // Forces focusout in IE graph.container.focus(); // Clears the DIV the non-DOM way - div.innerHTML = ''; + divtable.innerHTML = ''; // Gets the selection cell const cell = graph.getSelectionCell(); if (cell == null) { - domUtils.writeln(div, 'Nothing selected.'); + domUtils.writeln(divtable, 'Nothing selected.'); } else { // Writes the title const center = document.createElement('center'); domUtils.writeln(center, `${cell.value.nodeName} (${cell.id})`); - div.appendChild(center); - domUtils.br(div); + divtable.appendChild(center); + domUtils.br(divtable); // Creates the form from the attributes of the user object const form = new MaxForm(); @@ -235,9 +228,10 @@ const Template = ({ label, ...args }) => { for (let i = 0; i < attrs.length; i++) { createTextField(graph, form, cell, attrs[i]); } - - div.appendChild(form.getTable()); - domUtils.br(div); + const table= form.getTable() + table.setAttribute('id','properties'); + divtable.appendChild(table); + domUtils.br(divtable); } } @@ -275,7 +269,7 @@ const Template = ({ label, ...args }) => { // explicitely where we do the graph.focus above. InternalEvent.addListener(input, 'blur', applyHandler); } - return div; + return divlayout; }; export const Default = Template.bind({}); diff --git a/packages/html/stories/Validation.stories.js b/packages/html/stories/Validation.stories.js index eb1096d8ff..5669dc8a26 100644 --- a/packages/html/stories/Validation.stories.js +++ b/packages/html/stories/Validation.stories.js @@ -13,10 +13,10 @@ export default { title: 'Misc/Validation', argTypes: { ...globalTypes, - rubberBand: { - type: 'boolean', - defaultValue: true, - }, + // rubberBand: { + // type: 'boolean', + // defaultValue: true, + // }, }, }; @@ -89,6 +89,9 @@ const Template = ({ label, ...args }) => { // Enables rubberband selection new RubberBandHandler(graph); + // Transfer initial focus to graph container for keystroke handling + graph.container.focus(); + // Removes cells when [DELETE] is pressed const keyHandler = new KeyHandler(graph); keyHandler.bindKey(46, function (evt) { diff --git a/packages/html/stories/Visibility.stories.js b/packages/html/stories/Visibility.stories.js index 68bfc603f7..02eb597fdf 100644 --- a/packages/html/stories/Visibility.stories.js +++ b/packages/html/stories/Visibility.stories.js @@ -1,4 +1,4 @@ -import { Graph, RubberBandHandler, DomHelpers } from '@maxgraph/core'; +import { Graph, RubberBandHandler, DomHelpers, Cell} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -43,7 +43,7 @@ const Template = ({ label, ...args }) => { const isVisible = function () { // TODO super cannot be used here // let result = super.isVisible(); - let result; + let result=Cell.prototype.isVisible.apply(this, arguments); if (result && this.value != null) { result = (showOne && this.value == '1') || diff --git a/packages/html/stories/Window.stories.js b/packages/html/stories/Window.stories.js index e3975d3c8f..1265a09fbc 100644 --- a/packages/html/stories/Window.stories.js +++ b/packages/html/stories/Window.stories.js @@ -14,7 +14,6 @@ import { globalTypes } from '../.storybook/preview'; export default { title: 'Windows/Windows', argTypes: { - ...globalTypes, contextMenu: { type: 'boolean', defaultValue: false, @@ -30,13 +29,15 @@ const Template = ({ label, ...args }) => { Client.setImageBasePath('/images'); 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.position = 'absolute'; + container.style.overflow = 'auto'; + container.style.width = '100%'; + container.style.height = '100%'; + container.style.background = 'lightyellow'; container.style.cursor = 'default'; + + // Note that we're using the container scrollbars for the graph so that the // container extends to the parent div inside the window let wnd = new MaxWindow( @@ -118,7 +119,7 @@ const Template = ({ label, ...args }) => { MaxLog.show(); - return container; + return document.createElement('div'); }; export const Default = Template.bind({}); diff --git a/packages/html/stories/stashed/Ports.js b/packages/html/stories/stashed/Ports.js index 277a95a270..7c986b8a3c 100644 --- a/packages/html/stories/stashed/Ports.js +++ b/packages/html/stories/stashed/Ports.js @@ -20,6 +20,7 @@ import { createXmlDocument, getPrettyXml } from '../../packages/core/src/util/xm import { makeDraggable } from '../../packages/core/src/util/gestureUtils'; + const HTML_TEMPLATE = `