Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5048127
feat: let register and unregister default style elements
tbouffard Apr 11, 2025
0c9d467
Merge branch 'main' into feat/register_unregister_default_styles
tbouffard Apr 11, 2025
e89778f
edge markers: improve JSDoc
tbouffard Apr 11, 2025
1f252ae
fix typo in registerDefaultEdgStyles function name (missing "e")
tbouffard Apr 11, 2025
e7a7e1f
Examples: improve comments [skip ci]
tbouffard Apr 11, 2025
2d67db1
fix: remove extra call in registerDefaultEdgeStyles
tbouffard Apr 11, 2025
8aed80b
docs: mention unregister functions [skip ci]
tbouffard Apr 17, 2025
6baa5b2
Improve jsdoc of unregisterAllEdgeStylesAndPerimeters [skip ci]
tbouffard Apr 17, 2025
5968aa4
Move stencils to a dedicated directory
tbouffard Apr 17, 2025
178ba34
Add unregisterAllStencilShapes
tbouffard Apr 17, 2025
5f4f987
docs: list all unregister functions
tbouffard Apr 17, 2025
3d13833
use unregisterAllStencilShapes in stories
tbouffard Apr 17, 2025
60346ad
index.ts: reorg - group related exports
tbouffard Apr 17, 2025
162084f
jsdoc: add for EdgeMarker [skip ci]
tbouffard Apr 17, 2025
44a3ff4
Merge branch 'main' into feat/register_unregister_default_styles
tbouffard Apr 18, 2025
6b3d1a5
examples without defaults: do not unregister styles, never load them …
tbouffard Apr 18, 2025
a097261
Graph constructor: no need for stylesheet default value
tbouffard Apr 18, 2025
85bd665
fix JSDoc of createArrow
tbouffard Apr 22, 2025
7ab0941
docs: explain how to unregister codec only in the codec page (for con…
tbouffard Apr 22, 2025
3cad120
docs: explain how to register default styles configuration
tbouffard Apr 22, 2025
77f30d2
refactor Graph.registerDefaults: call of methods in alphabetic order …
tbouffard Apr 22, 2025
80f6c88
Merge branch 'main' into feat/register_unregister_default_styles
tbouffard Apr 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export { default as ArrowShape } from './view/geometry/edge/ArrowShape';
export { default as ArrowConnectorShape } from './view/geometry/edge/ArrowConnectorShape';
export { default as ConnectorShape } from './view/geometry/edge/ConnectorShape';
export { default as LineShape } from './view/geometry/edge/LineShape';
export { default as MarkerShape } from './view/geometry/edge/MarkerShape';
export { default as PolylineShape } from './view/geometry/edge/PolylineShape';

export { default as CloudShape } from './view/geometry/node/CloudShape';
Expand All @@ -115,11 +114,13 @@ export { default as HexagonShape } from './view/geometry/node/HexagonShape';
export { default as ImageShape } from './view/geometry/node/ImageShape';
export { default as RectangleShape } from './view/geometry/node/RectangleShape';
export { default as RhombusShape } from './view/geometry/node/RhombusShape';

export { unregisterAllStencilShapes } from './view/geometry/stencil/register';
export {
default as StencilShape,
StencilShapeConfig,
} from './view/geometry/node/StencilShape';
export { default as StencilShapeRegistry } from './view/geometry/node/StencilShapeRegistry';
} from './view/geometry/stencil/StencilShape';
export { default as StencilShapeRegistry } from './view/geometry/stencil/StencilShapeRegistry';

export * as constants from './util/Constants';
export { default as Guide } from './view/other/Guide';
Expand Down Expand Up @@ -157,6 +158,17 @@ export { default as Point } from './view/geometry/Point';
export { default as Rectangle } from './view/geometry/Rectangle';

export * from './view/style/config';
export * from './view/style/register';
export { default as MarkerShape } from './view/style/EdgeMarkerRegistry';
/**
* Includes all builtins edge markers which can be registered in {@link MarkerShape}.
*
* They are registered by default when instantiating {@link Graph} or they can all be registered by calling {@link registerDefaultEdgeMarkers}.
*
* @since 0.18.0
* @category Style
*/
export * as EdgeMarker from './view/style/edge-markers';
Comment thread
tbouffard marked this conversation as resolved.
export { default as EdgeStyle } from './view/style/EdgeStyle';
export { default as Perimeter } from './view/style/Perimeter';
export { default as StyleRegistry } from './view/style/StyleRegistry';
Expand Down Expand Up @@ -194,6 +206,7 @@ export { default as Clipboard } from './util/Clipboard';
export { default as UndoableEdit } from './view/undoable_changes/UndoableEdit';
export { default as UndoManager } from './view/undoable_changes/UndoManager';

export * from './view/cell/register-shapes';
export { Cell } from './view/cell/Cell';
export { default as CellOverlay } from './view/cell/CellOverlay';
export { default as CellPath } from './view/cell/CellPath';
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/serialization/register-model-codecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ import {
import Geometry from '../view/geometry/Geometry';
import Point from '../view/geometry/Point';
import ObjectCodec from './ObjectCodec';
import { registerBaseCodecs } from './register-shared';
import { CodecRegistrationStates, registerBaseCodecs } from './register-shared';

const createObjectCodec = (template: any, name: string): ObjectCodec => {
const objectCodec = new ObjectCodec(template);
objectCodec.setName(name);
return objectCodec;
};

let isModelCodecsRegistered = false;
/**
* Register model codecs i.e. codecs used to import/export the Graph Model, see {@link GraphDataModel}.
*
Expand All @@ -43,7 +42,7 @@ let isModelCodecsRegistered = false;
* @category Serialization with Codecs
*/
export const registerModelCodecs = (force = false) => {
if (!isModelCodecsRegistered || force) {
if (!CodecRegistrationStates.model || force) {
CodecRegistry.register(new CellCodec());
CodecRegistry.register(new ModelCodec());

Expand All @@ -59,6 +58,6 @@ export const registerModelCodecs = (force = false) => {
CodecRegistry.register(new mxCellCodec(), false);
CodecRegistry.register(new mxGeometryCodec(), false);

isModelCodecsRegistered = true;
CodecRegistrationStates.model = true;
}
};
29 changes: 22 additions & 7 deletions packages/core/src/serialization/register-other-codecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import GeometryChange from '../view/undoable_changes/GeometryChange';
import StyleChange from '../view/undoable_changes/StyleChange';
import ValueChange from '../view/undoable_changes/ValueChange';
import VisibleChange from '../view/undoable_changes/VisibleChange';
import { registerBaseCodecs } from './register-shared';
import { CodecRegistrationStates, registerBaseCodecs } from './register-shared';
import { registerModelCodecs } from './register-model-codecs';

const registerGenericChangeCodecs = () => {
Expand All @@ -59,7 +59,6 @@ const registerGenericChangeCodecs = () => {
);
};

let isCoreCodecsRegistered = false;
/**
* Register core codecs i.e. codecs that don't relate to editor. This includes model codecs that can be registered individually with {@link registerModelCodecs}.
*
Expand All @@ -70,7 +69,7 @@ let isCoreCodecsRegistered = false;
* @category Serialization with Codecs
*/
export const registerCoreCodecs = (force = false) => {
if (!isCoreCodecsRegistered || force) {
if (!CodecRegistrationStates.core || force) {
CodecRegistry.register(new ChildChangeCodec());
CodecRegistry.register(new GraphCodec());
CodecRegistry.register(new GraphViewCodec());
Expand All @@ -81,11 +80,10 @@ export const registerCoreCodecs = (force = false) => {

registerModelCodecs(force);

isCoreCodecsRegistered = true;
CodecRegistrationStates.core = true;
}
};

let isEditorCodecsRegistered = false;
/**
* Register only editor codecs.
* @param force if `true` register the codecs even if they were already registered. If false, only register them
Expand All @@ -95,15 +93,15 @@ let isEditorCodecsRegistered = false;
* @category Serialization with Codecs
*/
export const registerEditorCodecs = (force = false) => {
if (!isEditorCodecsRegistered || force) {
if (!CodecRegistrationStates.editor || force) {
registerBaseCodecs(force);

CodecRegistry.register(new EditorCodec());
CodecRegistry.register(new EditorKeyHandlerCodec());
CodecRegistry.register(new EditorPopupMenuCodec());
CodecRegistry.register(new EditorToolbarCodec());

isEditorCodecsRegistered = true;
CodecRegistrationStates.editor = true;
}
};

Expand All @@ -120,3 +118,20 @@ export const registerAllCodecs = (force = false) => {
registerCoreCodecs(force);
registerEditorCodecs(force);
};

/**
* Unregister all codecs from {@link CodecRegistry}.
*
* @since 0.18.0
* @category Configuration
* @category Serialization with Codecs
*/
export const unregisterAllCodecs = () => {
CodecRegistry.codecs = {};
CodecRegistry.aliases = {};

// reset the state to ensure that the codecs are registered again when the "register" functions are called
for (const key of Object.keys(CodecRegistrationStates)) {
CodecRegistrationStates[key] = false;
}
};
20 changes: 16 additions & 4 deletions packages/core/src/serialization/register-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// These functions are private and are not intended to be exported by the npm package
// The elements in this file are private and are not intended to be exported by the npm package

import CodecRegistry from './CodecRegistry';
import ObjectCodec from './ObjectCodec';

let isBaseCodecsRegistered = false;
/**
* @private
*/
export const CodecRegistrationStates: Record<string, boolean> = {
base: false,
core: false,
editor: false,
model: false,
};

/**
* @private
*/
export const registerBaseCodecs = (force = false) => {
if (!isBaseCodecsRegistered || force) {
if (!CodecRegistrationStates.base || force) {
CodecRegistry.register(new ObjectCodec({})); // Object
CodecRegistry.register(new ObjectCodec([])); // Array

isBaseCodecsRegistered = true;
CodecRegistrationStates.base = true;
}
};
14 changes: 9 additions & 5 deletions packages/core/src/view/Graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ import Multiplicity from './other/Multiplicity';
import ImageBundle from './image/ImageBundle';
import GraphSelectionModel from './GraphSelectionModel';
import { registerDefaultShapes } from './cell/register-shapes';
import { registerDefaultEdgeMarkers } from './geometry/edge/MarkerShape';
import { registerDefaultStyleElements } from './style/register';
import {
registerDefaultEdgeMarkers,
registerDefaultEdgeStyles,
registerDefaultPerimeters,
} from './style/register';
import { applyGraphMixins } from './mixins/_graph-mixins-apply';
import { getDefaultPlugins } from './plugins';
import { isNullish } from '../internal/utils';
Expand Down Expand Up @@ -488,16 +491,17 @@ class Graph extends EventSource {
// ===================================================================================================================

protected registerDefaults(): void {
registerDefaultShapes();
registerDefaultStyleElements();
registerDefaultEdgeMarkers();
registerDefaultEdgeStyles();
registerDefaultPerimeters();
registerDefaultShapes();
}

constructor(
container?: HTMLElement,
model?: GraphDataModel,
plugins: GraphPluginConstructor[] = getDefaultPlugins(),
stylesheet: Stylesheet | null = null
stylesheet?: Stylesheet | null
) {
super();
this.registerDefaults();
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/view/cell/CellRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { getRotatedPoint, mod, toRadians } from '../../util/mathUtils';
import { convertPoint } from '../../util/styleUtils';
import { equalEntries, equalPoints } from '../../util/arrayUtils';
import Rectangle from '../geometry/Rectangle';
import StencilShapeRegistry from '../geometry/node/StencilShapeRegistry';
import StencilShapeRegistry from '../geometry/stencil/StencilShapeRegistry';
import InternalEvent from '../event/InternalEvent';
import Client from '../../Client';
import InternalMouseEvent from '../event/InternalMouseEvent';
Expand Down
16 changes: 14 additions & 2 deletions packages/core/src/view/cell/register-shapes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ import { SHAPE } from '../../util/Constants';
let isDefaultElementsRegistered = false;

/**
* Add default shapes into `CellRenderer` shapes.
* Register default builtin shapes into {@link CellRenderer}.
*
* @private
* @category Configuration
* @category Style
* @since 0.18.0
*/
export function registerDefaultShapes() {
if (!isDefaultElementsRegistered) {
Expand Down Expand Up @@ -70,3 +70,15 @@ export function registerDefaultShapes() {
isDefaultElementsRegistered = true;
}
}

/**
* Unregister all shapes from {@link CellRenderer}.
*
* @category Configuration
* @category Style
* @since 0.18.0
*/
export function unregisterAllShapes() {
CellRenderer.defaultShapes = {};
isDefaultElementsRegistered = false;
}
2 changes: 1 addition & 1 deletion packages/core/src/view/geometry/Shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import SvgCanvas2D from '../canvas/SvgCanvas2D';
import InternalEvent from '../event/InternalEvent';
import Client from '../../Client';
import type CellState from '../cell/CellState';
import type StencilShape from './node/StencilShape';
import type StencilShape from './stencil/StencilShape';
import type CellOverlay from '../cell/CellOverlay';
import type ImageBox from '../image/ImageBox';
import type {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/view/geometry/edge/ConnectorShape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ limitations under the License.

import { DEFAULT_MARKERSIZE, NONE } from '../../../util/Constants';
import PolylineShape from './PolylineShape';
import MarkerShape from './MarkerShape';
import MarkerShape from '../../style/EdgeMarkerRegistry';
import Point from '../Point';
import AbstractCanvas2D from '../../canvas/AbstractCanvas2D';
import Rectangle from '../Rectangle';
Expand Down
28 changes: 28 additions & 0 deletions packages/core/src/view/geometry/stencil/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright 2025-present The maxGraph project Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import StencilShapeRegistry from './StencilShapeRegistry';

/**
* Unregister all {@link StencilShape}s from {@link StencilShapeRegistry}.
*
* @category Configuration
* @category Style
* @since 0.18.0
*/
export function unregisterAllStencilShapes() {
StencilShapeRegistry.stencils = {};
}
67 changes: 67 additions & 0 deletions packages/core/src/view/style/EdgeMarkerRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
Copyright 2021-present The maxGraph project Contributors
Copyright (c) 2006-2015, JGraph Ltd
Copyright (c) 2006-2015, Gaudenz Alder

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import type { MarkerFactoryFunction, StyleArrowValue } from '../../types';
import type AbstractCanvas2D from '../canvas/AbstractCanvas2D';
import type Point from '../geometry/Point';
import type Shape from '../geometry/Shape';

/**
* A registry that stores the factory functions that create edge markers.
*
* NOTE: The signature and the name of in this class will change.
*/
class MarkerShape {
/**
* Maps from markers names to functions to paint the markers.
*
* Mapping: the attribute name on the object is the marker type, the associated value is the function to paint the marker
*/
static markers: Record<string, MarkerFactoryFunction> = {};

/**
* Adds a factory method that updates a given endpoint and returns a
* function to paint the marker onto the given canvas.
*/
static addMarker(type: string, funct: MarkerFactoryFunction) {
MarkerShape.markers[type] = funct;
}

/**
* Returns a function to paint the given marker.
*/
static createMarker(
canvas: AbstractCanvas2D,
shape: Shape,
type: StyleArrowValue,
pe: Point,
unitX: number,
unitY: number,
size: number,
source: boolean,
sw: number,
filled: boolean
) {
const markerFunction = MarkerShape.markers[type];
return markerFunction
? markerFunction(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled)
: null;
}
}

export default MarkerShape;
Loading