This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new c91692e0439 kie-issues#842: The new DMN editor resets the node color
styles to its initial value after an edit (#2143)
c91692e0439 is described below
commit c91692e043901780779b340042900b20272d77e5
Author: Tiago Bento <[email protected]>
AuthorDate: Mon Feb 5 22:51:37 2024 -0500
kie-issues#842: The new DMN editor resets the node color styles to its
initial value after an edit (#2143)
---
.../dmn-editor/src/propertiesPanel/FontOptions.tsx | 178 ++++++++--------
.../src/propertiesPanel/ShapeOptions.tsx | 225 ++++++++++++---------
.../src/propertiesPanel/SingleNodeProperties.tsx | 5 +-
3 files changed, 226 insertions(+), 182 deletions(-)
diff --git a/packages/dmn-editor/src/propertiesPanel/FontOptions.tsx
b/packages/dmn-editor/src/propertiesPanel/FontOptions.tsx
index d8ba5278f6c..0e9ba4418ee 100644
--- a/packages/dmn-editor/src/propertiesPanel/FontOptions.tsx
+++ b/packages/dmn-editor/src/propertiesPanel/FontOptions.tsx
@@ -17,24 +17,24 @@
* under the License.
*/
-import * as React from "react";
-import { useState, useMemo, useCallback, useEffect } from "react";
+import { DMNDI15__DMNShape } from
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
+import { Button, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
import { FormSection } from "@patternfly/react-core/dist/js/components/Form";
-import { PencilAltIcon } from
"@patternfly/react-icons/dist/js/icons/pencil-alt-icon";
-import { PropertiesPanelHeader } from "./PropertiesPanelHeader";
-import { State } from "../store/Store";
-import { useDmnEditorStore, useDmnEditorStoreApi } from
"../store/StoreContext";
import { NumberInput } from
"@patternfly/react-core/dist/js/components/NumberInput";
-import { DMNDI15__DMNShape } from
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
-import { addOrGetDrd } from "../mutations/addOrGetDrd";
+import { Select, SelectOption, SelectVariant } from
"@patternfly/react-core/dist/js/components/Select";
import { ToggleGroup, ToggleGroupItem } from
"@patternfly/react-core/dist/js/components/ToggleGroup";
-import { Select, SelectVariant, SelectOption } from
"@patternfly/react-core/dist/js/components/Select";
-import { useInViewSelect } from "../responsiveness/useInViewSelect";
-import { useDmnEditor } from "../DmnEditorContext";
-import { Button, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
-import { UndoAltIcon } from
"@patternfly/react-icons/dist/js/icons/undo-alt-icon";
import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { PencilAltIcon } from
"@patternfly/react-icons/dist/js/icons/pencil-alt-icon";
+import { UndoAltIcon } from
"@patternfly/react-icons/dist/js/icons/undo-alt-icon";
+import * as React from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { useDmnEditor } from "../DmnEditorContext";
+import { addOrGetDrd } from "../mutations/addOrGetDrd";
+import { useInViewSelect } from "../responsiveness/useInViewSelect";
+import { State } from "../store/Store";
+import { useDmnEditorStore, useDmnEditorStoreApi } from
"../store/StoreContext";
import { ColorPicker } from "./ColorPicker";
+import { PropertiesPanelHeader } from "./PropertiesPanelHeader";
import "./FontOptions.css";
// https://www.w3schools.com/cssref/css_websafe_fonts.php
@@ -51,6 +51,7 @@ const WEBSAFE_FONTS_LIST = [
"Brush Script MT",
];
+const DEFAULT_FONT_COLOR = { "@_blue": 0, "@_green": 0, "@_red": 0 };
const DEFAULT_FONT_SIZE = 16;
const MAX_FONT_SIZE = 72;
const MIN_FONT_SIZE = 0;
@@ -65,40 +66,48 @@ enum FontStyleToggleOptions {
export function FontOptions({ startExpanded, nodeIds }: { startExpanded:
boolean; nodeIds: string[] }) {
const dmnEditorStoreApi = useDmnEditorStoreApi();
- const [isStyleSectionExpanded, setStyleSectionExpanded] =
useState<boolean>(startExpanded);
- const dmnShapesByHref = useDmnEditorStore((s) =>
s.computed(s).indexes().dmnShapesByHref);
- const shapes = useMemo(() => nodeIds.map((nodeId) =>
dmnShapesByHref.get(nodeId)), [dmnShapesByHref, nodeIds]);
- const shapesStyle = useMemo(() => shapes.map((shape) =>
shape?.["di:Style"]), [shapes]);
+ const shapeStyles = useDmnEditorStore((s) =>
+ nodeIds.map((nodeId) =>
s.computed(s).indexes().dmnShapesByHref.get(nodeId)?.["di:Style"])
+ );
- const fontFamily = useMemo(() => shapesStyle[0]?.["@_fontFamily"],
[shapesStyle]);
- const isFontBold = useMemo(() => shapesStyle[0]?.["@_fontBold"] ?? false,
[shapesStyle]);
- const isFontItalic = useMemo(() => shapesStyle[0]?.["@_fontItalic"] ??
false, [shapesStyle]);
- const isFontUnderline = useMemo(() => shapesStyle[0]?.["@_fontUnderline"],
[shapesStyle]);
- const isFontStrikeThrough = useMemo(() =>
shapesStyle[0]?.["@_fontStrikeThrough"] ?? false, [shapesStyle]);
- const fontSize = useMemo(() => shapesStyle[0]?.["@_fontSize"] ??
DEFAULT_FONT_SIZE, [shapesStyle]);
+ const fontFamily = useMemo(() => shapeStyles[0]?.["@_fontFamily"],
[shapeStyles]);
+ const isFontBold = useMemo(() => shapeStyles[0]?.["@_fontBold"] ?? false,
[shapeStyles]);
+ const isFontItalic = useMemo(() => shapeStyles[0]?.["@_fontItalic"] ??
false, [shapeStyles]);
+ const isFontUnderline = useMemo(() => shapeStyles[0]?.["@_fontUnderline"],
[shapeStyles]);
+ const isFontStrikeThrough = useMemo(() =>
shapeStyles[0]?.["@_fontStrikeThrough"] ?? false, [shapeStyles]);
+ const fontSize = useMemo(() => shapeStyles[0]?.["@_fontSize"] ??
DEFAULT_FONT_SIZE, [shapeStyles]);
const fontColor = useMemo(() => {
- const b = (shapesStyle[0]?.["dmndi:FontColor"]?.["@_blue"] ??
0).toString(16);
- const g = (shapesStyle[0]?.["dmndi:FontColor"]?.["@_green"] ??
0).toString(16);
- const r = (shapesStyle[0]?.["dmndi:FontColor"]?.["@_red"] ??
0).toString(16);
+ const b = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_blue"] ??
DEFAULT_FONT_COLOR["@_red"]).toString(16);
+ const g = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_green"] ??
DEFAULT_FONT_COLOR["@_green"]).toString(16);
+ const r = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_red"] ??
DEFAULT_FONT_COLOR["@_blue"]).toString(16);
return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g :
g}${b.length === 1 ? "0" + b : b}`;
- }, [shapesStyle]);
+ }, [shapeStyles]);
+
+ const [isStyleSectionExpanded, setStyleSectionExpanded] =
useState<boolean>(startExpanded);
- const editShapeStyle = useCallback(
+ const setShapeStyles = useCallback(
(callback: (shape: DMNDI15__DMNShape[], state: State) => void) => {
- dmnEditorStoreApi.setState((state) => {
- const { diagramElements } = addOrGetDrd({
- definitions: state.dmn.model.definitions,
- drdIndex: state.diagram.drdIndex,
- });
- const _shapes = shapes.map((shape) => diagramElements[shape?.index ??
0]);
- _shapes.forEach((_shape, i, _shapes) => {
- _shapes[i]["di:Style"] ??= { __$$element: "dmndi:DMNStyle" };
+ dmnEditorStoreApi.setState((s) => {
+ const { diagramElements } = addOrGetDrd({ definitions:
s.dmn.model.definitions, drdIndex: s.diagram.drdIndex });
+
+ const shapes = nodeIds.map((nodeId) => {
+ const shape = s.computed(s).indexes().dmnShapesByHref.get(nodeId);
+ if (!shape) {
+ throw new Error(`DMN Shape for '${nodeId}' does not exist.`);
+ }
+
+ return diagramElements[shape.index];
});
- callback(_shapes, state);
+
+ for (const shape of shapes) {
+ shape["di:Style"] ??= { __$$element: "dmndi:DMNStyle" };
+ }
+
+ callback(shapes, s);
});
},
- [dmnEditorStoreApi, shapes]
+ [dmnEditorStoreApi, nodeIds]
);
const { dmnEditorRootElementRef } = useDmnEditor();
@@ -109,20 +118,20 @@ export function FontOptions({ startExpanded, nodeIds }: {
startExpanded: boolean
const onSelectFont = useCallback(
(e, value, isPlaceholder) => {
if (isPlaceholder) {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape, i, shapes) => {
shape["di:Style"]!["@_fontFamily"] ??= undefined;
});
});
- return;
- }
- editShapeStyle((shapes) => {
- shapes.forEach((shape, i, shapes) => {
- shape["di:Style"]!["@_fontFamily"] = value;
+ } else {
+ setShapeStyles((shapes) => {
+ shapes.forEach((shape, i, shapes) => {
+ shape["di:Style"]!["@_fontFamily"] = value;
+ });
});
- });
+ }
},
- [editShapeStyle]
+ [setShapeStyles]
);
const validateFontSize = useCallback((value?: number): number => {
@@ -139,111 +148,108 @@ export function FontOptions({ startExpanded, nodeIds }:
{ startExpanded: boolean
}, []);
const onMinus = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontSize"] = validateFontSize(
(shape!["di:Style"]?.["@_fontSize"] ?? DEFAULT_FONT_SIZE) - 1
);
});
});
- }, [editShapeStyle, validateFontSize]);
+ }, [setShapeStyles, validateFontSize]);
const onChange = useCallback(
(event: React.FormEvent<HTMLInputElement>) => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontSize"] = +(event.target as
HTMLInputElement).value;
});
});
},
- [editShapeStyle]
+ [setShapeStyles]
);
const onPlus = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontSize"] = validateFontSize(
(shape!["di:Style"]?.["@_fontSize"] ?? DEFAULT_FONT_SIZE) + 1
);
});
});
- }, [editShapeStyle, validateFontSize]);
+ }, [setShapeStyles, validateFontSize]);
const onChangeBold = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontBold"] =
!shape?.["di:Style"]?.["@_fontBold"] ?? true;
});
});
- }, [editShapeStyle]);
+ }, [setShapeStyles]);
const onChangeItalic = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontItalic"] =
!shape?.["di:Style"]?.["@_fontItalic"] ?? true;
});
});
- }, [editShapeStyle]);
+ }, [setShapeStyles]);
const onChangeUnderline = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontUnderline"] =
!shape?.["di:Style"]?.["@_fontUnderline"] ?? true;
});
});
- }, [editShapeStyle]);
+ }, [setShapeStyles]);
const onChangeStrikeThrough = useCallback(() => {
- editShapeStyle((shapes) => {
+ setShapeStyles((shapes) => {
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontStrikeThrough"] =
!shape?.["di:Style"]?.["@_fontStrikeThrough"] ?? true;
});
});
- }, [editShapeStyle]);
+ }, [setShapeStyles]);
const colorPickerRef = React.useRef<HTMLInputElement>(null) as
React.MutableRefObject<HTMLInputElement>;
- const [temporaryFontColor, setTemporaryFontColor] =
useState<string>("000000");
+ const [temporaryFontColor, setTemporaryFontColor] = useState<string |
undefined>();
const onChangeColor = useCallback(
(newColor: string) => {
setTemporaryFontColor(newColor.replace("#", ""));
- editShapeStyle((shapes, state) => {
- state!.diagram.isEditingStyle = true;
+ setShapeStyles((shapes, state) => {
+ state.diagram.isEditingStyle = true;
});
},
- [editShapeStyle]
+ [setShapeStyles]
);
useEffect(() => {
const timeout = setTimeout(() => {
- const red = parseInt(temporaryFontColor.slice(0, 2), 16);
- const green = parseInt(temporaryFontColor.slice(2, 4), 16);
- const blue = parseInt(temporaryFontColor.slice(4, 6), 16);
- editShapeStyle((shapes, state) => {
+ if (!temporaryFontColor) {
+ return;
+ }
+
+ setTemporaryFontColor(undefined);
+
+ setShapeStyles((shapes, state) => {
shapes.forEach((shape) => {
- if (
- red !== shape?.["di:Style"]?.["dmndi:FontColor"]?.["@_red"] &&
- green !== shape?.["di:Style"]?.["dmndi:FontColor"]?.["@_green"] &&
- blue !== shape?.["di:Style"]?.["dmndi:FontColor"]?.["@_blue"]
- ) {
- state!.diagram.isEditingStyle = false;
- shape!["di:Style"]!["dmndi:FontColor"] ??= { "@_blue": 0,
"@_green": 0, "@_red": 0 };
- shape!["di:Style"]!["dmndi:FontColor"]["@_red"] = red;
- shape!["di:Style"]!["dmndi:FontColor"]["@_green"] = green;
- shape!["di:Style"]!["dmndi:FontColor"]["@_blue"] = blue;
- }
+ state.diagram.isEditingStyle = false;
+ shape["di:Style"]!["dmndi:FontColor"] ??= DEFAULT_FONT_COLOR;
+ shape["di:Style"]!["dmndi:FontColor"]["@_red"] =
parseInt(temporaryFontColor.slice(0, 2), 16);
+ shape["di:Style"]!["dmndi:FontColor"]["@_green"] =
parseInt(temporaryFontColor.slice(2, 4), 16);
+ shape["di:Style"]!["dmndi:FontColor"]["@_blue"] =
parseInt(temporaryFontColor.slice(4, 6), 16);
});
});
}, 0);
+
return () => {
clearTimeout(timeout);
};
- }, [editShapeStyle, temporaryFontColor]);
+ }, [setShapeStyles, temporaryFontColor]);
const onReset = useCallback(() => {
- setTemporaryFontColor("000000");
- editShapeStyle((shapes, state) => {
- state!.diagram.isEditingStyle = false;
+ setShapeStyles((shapes, state) => {
+ state.diagram.isEditingStyle = false;
shapes.forEach((shape) => {
shape["di:Style"]!["@_fontBold"] = undefined;
shape["di:Style"]!["@_fontItalic"] = undefined;
@@ -251,9 +257,13 @@ export function FontOptions({ startExpanded, nodeIds }: {
startExpanded: boolean
shape["di:Style"]!["@_fontStrikeThrough"] = undefined;
shape["di:Style"]!["@_fontSize"] = undefined;
shape["di:Style"]!["@_fontFamily"] = undefined;
+ shape["di:Style"]!["dmndi:FontColor"] ??= DEFAULT_FONT_COLOR;
+ shape["di:Style"]!["dmndi:FontColor"]["@_red"] =
DEFAULT_FONT_COLOR["@_red"];
+ shape["di:Style"]!["dmndi:FontColor"]["@_green"] =
DEFAULT_FONT_COLOR["@_green"];
+ shape["di:Style"]!["dmndi:FontColor"]["@_blue"] =
DEFAULT_FONT_COLOR["@_blue"];
});
});
- }, [editShapeStyle]);
+ }, [setShapeStyles]);
return (
<>
diff --git a/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx
b/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx
index 0b0bbdcb786..472efc48fe0 100644
--- a/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx
+++ b/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx
@@ -35,6 +35,9 @@ import { ColorPicker } from "./ColorPicker";
import { ToggleGroup, ToggleGroupItem } from
"@patternfly/react-core/dist/js/components/ToggleGroup";
import "./ShapeOptions.css";
+const DEFAULT_FILL_COLOR = { "@_blue": 255, "@_green": 255, "@_red": 255 };
+const DEFAULT_STROKE_COLOR = { "@_blue": 0, "@_green": 0, "@_red": 0 };
+
export function ShapeOptions({
startExpanded,
nodeIds,
@@ -46,178 +49,208 @@ export function ShapeOptions({
isDimensioningEnabled: boolean;
isPositioningEnabled: boolean;
}) {
- const [isShapeSectionExpanded, setShapeSectionExpanded] =
useState<boolean>(startExpanded);
const dmnEditorStoreApi = useDmnEditorStoreApi();
- const dmnShapesByHref = useDmnEditorStore((s) =>
s.computed(s).indexes().dmnShapesByHref);
- const shapes = useMemo(() => nodeIds.map((nodeId) =>
dmnShapesByHref.get(nodeId)), [dmnShapesByHref, nodeIds]);
- // it only edits the first selected node
- const shapesBound = useMemo(() => shapes[0]?.["dc:Bounds"], [shapes]);
- const shapesStyle = useMemo(() => shapes.map((shape) =>
shape?.["di:Style"]), [shapes]);
+ const shapes = useDmnEditorStore((s) => nodeIds.map((nodeId) =>
s.computed(s).indexes().dmnShapesByHref.get(nodeId)));
+ const shapeStyles = useMemo(() => shapes.map((shape) =>
shape?.["di:Style"]), [shapes]);
- const boundWidth = useMemo(() => +(shapesBound?.["@_width"]?.toFixed(2) ??
""), [shapesBound]);
- const boundHeight = useMemo(() => +(shapesBound?.["@_height"]?.toFixed(2) ??
""), [shapesBound]);
- const boundPositionX = useMemo(() => +(shapesBound?.["@_x"]?.toFixed(2) ??
""), [shapesBound]);
- const boundPositionY = useMemo(() => +(shapesBound?.["@_y"]?.toFixed(2) ??
""), [shapesBound]);
+ // For when a single node is selected.
+ const shapeBound = useMemo(() => shapes[0]?.["dc:Bounds"], [shapes]);
+ const boundWidth = useMemo(() => +(shapeBound?.["@_width"]?.toFixed(2) ??
""), [shapeBound]);
+ const boundHeight = useMemo(() => +(shapeBound?.["@_height"]?.toFixed(2) ??
""), [shapeBound]);
+ const boundPositionX = useMemo(() => +(shapeBound?.["@_x"]?.toFixed(2) ??
""), [shapeBound]);
+ const boundPositionY = useMemo(() => +(shapeBound?.["@_y"]?.toFixed(2) ??
""), [shapeBound]);
const fillColor = useMemo(() => {
- const b = (shapesStyle[0]?.["dmndi:FillColor"]?.["@_blue"] ??
255).toString(16);
- const g = (shapesStyle[0]?.["dmndi:FillColor"]?.["@_green"] ??
255).toString(16);
- const r = (shapesStyle[0]?.["dmndi:FillColor"]?.["@_red"] ??
255).toString(16);
+ const b = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_blue"] ??
DEFAULT_FILL_COLOR["@_red"]).toString(16);
+ const g = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_green"] ??
DEFAULT_FILL_COLOR["@_green"]).toString(16);
+ const r = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_red"] ??
DEFAULT_FILL_COLOR["@_blue"]).toString(16);
return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g :
g}${b.length === 1 ? "0" + b : b}`;
- }, [shapesStyle]);
+ }, [shapeStyles]);
+
const strokeColor = useMemo(() => {
- const b = (shapesStyle[0]?.["dmndi:StrokeColor"]?.["@_blue"] ??
0).toString(16);
- const g = (shapesStyle[0]?.["dmndi:StrokeColor"]?.["@_green"] ??
0).toString(16);
- const r = (shapesStyle[0]?.["dmndi:StrokeColor"]?.["@_red"] ??
0).toString(16);
+ const b = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_blue"] ??
DEFAULT_STROKE_COLOR["@_red"]).toString(16);
+ const g = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_green"] ??
DEFAULT_STROKE_COLOR["@_green"]).toString(16);
+ const r = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_red"] ??
DEFAULT_STROKE_COLOR["@_blue"]).toString(16);
return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g :
g}${b.length === 1 ? "0" + b : b}`;
- }, [shapesStyle]);
-
- const editNodeBound = useCallback(
- (callback: (bound?: DC__Bounds, state?: State) => void) => {
- dmnEditorStoreApi.setState((state) => {
- const { diagramElements } = addOrGetDrd({
- definitions: state.dmn.model.definitions,
- drdIndex: state.diagram.drdIndex,
- });
- const shape = diagramElements?.[shapes[0]?.index ?? 0] as
DMNDI15__DMNShape | undefined;
- callback(shape?.["dc:Bounds"], state);
+ }, [shapeStyles]);
+
+ const [isShapeSectionExpanded, setShapeSectionExpanded] =
useState<boolean>(startExpanded);
+
+ const setBounds = useCallback(
+ (callback: (bounds: DC__Bounds, state: State) => void) => {
+ dmnEditorStoreApi.setState((s) => {
+ const { diagramElements } = addOrGetDrd({ definitions:
s.dmn.model.definitions, drdIndex: s.diagram.drdIndex });
+
+ const index = nodeIds.map((nodeId) =>
s.computed(s).indexes().dmnShapesByHref.get(nodeId))[0]?.index ?? -1;
+ if (index < 0) {
+ throw new Error(`DMN Shape for '${nodeIds[0]}' does not exist.`);
+ }
+
+ const shape = diagramElements?.[index];
+
+ if (shape.__$$element !== "dmndi:DMNShape") {
+ throw new Error(`DMN Element with index ${index} is not a
DMNShape.`);
+ }
+
+ shape["dc:Bounds"] ??= { "@_height": 0, "@_width": 0, "@_x": 0, "@_y":
0 };
+
+ callback(shape["dc:Bounds"], s);
});
},
- [dmnEditorStoreApi, shapes]
+ [dmnEditorStoreApi, nodeIds]
);
const onChangeWidth = useCallback(
(newWidth: string) => {
- editNodeBound((bound) => {
- bound!["@_width"] = +parseFloat(newWidth).toFixed(2);
+ setBounds((bounds) => {
+ bounds["@_width"] = +parseFloat(newWidth).toFixed(2);
});
},
- [editNodeBound]
+ [setBounds]
);
const onChangeHeight = useCallback(
(newHeight: string) => {
- editNodeBound((bound) => {
- bound!["@_height"] = +parseFloat(newHeight).toFixed(2);
+ setBounds((bounds) => {
+ bounds["@_height"] = +parseFloat(newHeight).toFixed(2);
});
},
- [editNodeBound]
+ [setBounds]
);
const onChangePositionX = useCallback(
(newX: string) => {
- editNodeBound((bound) => {
- bound!["@_x"] = +parseFloat(newX).toFixed(2);
+ setBounds((bounds) => {
+ bounds["@_x"] = +parseFloat(newX).toFixed(2);
});
},
- [editNodeBound]
+ [setBounds]
);
const onChangePositionY = useCallback(
(newY: string) => {
- editNodeBound((bound) => {
- bound!["@_y"] = +parseFloat(newY).toFixed(2);
+ setBounds((bounds) => {
+ bounds["@_y"] = +parseFloat(newY).toFixed(2);
});
},
- [editNodeBound]
+ [setBounds]
);
- const editShapeStyle = useCallback(
- (callback: (shape: DMNDI15__DMNShape[], state?: State) => void) => {
- dmnEditorStoreApi.setState((state) => {
- const { diagramElements } = addOrGetDrd({
- definitions: state.dmn.model.definitions,
- drdIndex: state.diagram.drdIndex,
- });
- const _shapes = shapes.map((shape) => diagramElements[shape?.index ??
0]);
- _shapes.forEach((_shape, i, _shapes) => {
- _shapes[i]["di:Style"] ??= { __$$element: "dmndi:DMNStyle" };
+ const setShapeStyles = useCallback(
+ (callback: (shape: DMNDI15__DMNShape[], state: State) => void) => {
+ dmnEditorStoreApi.setState((s) => {
+ const { diagramElements } = addOrGetDrd({ definitions:
s.dmn.model.definitions, drdIndex: s.diagram.drdIndex });
+
+ const shapes = nodeIds.map((nodeId) => {
+ const shape = s.computed(s).indexes().dmnShapesByHref.get(nodeId);
+ if (!shape) {
+ throw new Error(`DMN Shape for '${nodeId}' does not exist.`);
+ }
+
+ return diagramElements[shape.index];
});
- callback(_shapes, state);
+
+ let i = 0;
+ for (const shape of shapes) {
+ if (shape.__$$element !== "dmndi:DMNShape") {
+ throw new Error(`DMN Element with index ${i++} is not a
DMNShape.`);
+ }
+
+ shape["di:Style"] ??= { __$$element: "dmndi:DMNStyle" };
+ }
+
+ callback(shapes, s);
});
},
- [dmnEditorStoreApi, shapes]
+ [dmnEditorStoreApi, nodeIds]
);
- const [temporaryStrokeColor, setTemporaryStrokeColor] =
useState<string>("000000");
+ const [temporaryStrokeColor, setTemporaryStrokeColor] = useState<string |
undefined>();
const onChangeStrokeColor = useCallback(
(newColor: string) => {
setTemporaryStrokeColor(newColor.replace("#", ""));
- editShapeStyle((shapes, state) => {
- state!.diagram.isEditingStyle = true;
+ setShapeStyles((shapes, state) => {
+ state.diagram.isEditingStyle = true;
});
},
- [editShapeStyle]
+ [setShapeStyles]
);
useEffect(() => {
const timeout = setTimeout(() => {
- const red = parseInt(temporaryStrokeColor.slice(0, 2), 16);
- const green = parseInt(temporaryStrokeColor.slice(2, 4), 16);
- const blue = parseInt(temporaryStrokeColor.slice(4, 6), 16);
- editShapeStyle((shapes, state) => {
+ if (!temporaryStrokeColor) {
+ return;
+ }
+
+ setTemporaryStrokeColor(undefined);
+
+ setShapeStyles((shapes, state) => {
shapes.forEach((shape) => {
- if (
- red !== shape?.["di:Style"]?.["dmndi:StrokeColor"]?.["@_red"] &&
- green !== shape?.["di:Style"]?.["dmndi:StrokeColor"]?.["@_green"]
&&
- blue !== shape?.["di:Style"]?.["dmndi:StrokeColor"]?.["@_blue"]
- ) {
- state!.diagram.isEditingStyle = false;
- shape!["di:Style"]!["dmndi:StrokeColor"] ??= { "@_blue": 0,
"@_green": 0, "@_red": 0 };
- shape!["di:Style"]!["dmndi:StrokeColor"]["@_red"] = red;
- shape!["di:Style"]!["dmndi:StrokeColor"]["@_green"] = green;
- shape!["di:Style"]!["dmndi:StrokeColor"]["@_blue"] = blue;
- }
+ state.diagram.isEditingStyle = false;
+ shape!["di:Style"]!["dmndi:StrokeColor"] ??= DEFAULT_STROKE_COLOR;
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_red"] =
parseInt(temporaryStrokeColor.slice(0, 2), 16);
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_green"] =
parseInt(temporaryStrokeColor.slice(2, 4), 16);
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_blue"] =
parseInt(temporaryStrokeColor.slice(4, 6), 16);
});
});
}, 0);
+
return () => {
clearTimeout(timeout);
};
- }, [editShapeStyle, temporaryStrokeColor]);
+ }, [setShapeStyles, temporaryStrokeColor]);
- const [temporaryFillColor, setTemporaryFillColor] =
useState<string>("ffffff");
+ const [temporaryFillColor, setTemporaryFillColor] = useState<string |
undefined>();
const onChangeFillColor = useCallback(
(newColor: string) => {
setTemporaryFillColor(newColor.replace("#", ""));
- editShapeStyle((shapes, state) => {
- state!.diagram.isEditingStyle = true;
+ setShapeStyles((shapes, state) => {
+ state.diagram.isEditingStyle = true;
});
},
- [editShapeStyle]
+ [setShapeStyles]
);
useEffect(() => {
const timeout = setTimeout(() => {
- const red = parseInt(temporaryFillColor.slice(0, 2), 16);
- const green = parseInt(temporaryFillColor.slice(2, 4), 16);
- const blue = parseInt(temporaryFillColor.slice(4, 6), 16);
- editShapeStyle((shapes, state) => {
+ if (!temporaryFillColor) {
+ return;
+ }
+
+ setTemporaryFillColor(undefined);
+
+ setShapeStyles((shapes, state) => {
shapes.forEach((shape) => {
- if (
- red !== shape?.["di:Style"]?.["dmndi:FillColor"]?.["@_red"] &&
- green !== shape?.["di:Style"]?.["dmndi:FillColor"]?.["@_green"] &&
- blue !== shape?.["di:Style"]?.["dmndi:FillColor"]?.["@_blue"]
- ) {
- state!.diagram.isEditingStyle = false;
- shape!["di:Style"]!["dmndi:FillColor"] ??= { "@_blue": 255,
"@_green": 255, "@_red": 255 };
- shape!["di:Style"]!["dmndi:FillColor"]["@_red"] = red;
- shape!["di:Style"]!["dmndi:FillColor"]["@_green"] = green;
- shape!["di:Style"]!["dmndi:FillColor"]["@_blue"] = blue;
- }
+ state.diagram.isEditingStyle = false;
+ shape!["di:Style"]!["dmndi:FillColor"] ??= DEFAULT_FILL_COLOR;
+ shape!["di:Style"]!["dmndi:FillColor"]["@_red"] =
parseInt(temporaryFillColor.slice(0, 2), 16);
+ shape!["di:Style"]!["dmndi:FillColor"]["@_green"] =
parseInt(temporaryFillColor.slice(2, 4), 16);
+ shape!["di:Style"]!["dmndi:FillColor"]["@_blue"] =
parseInt(temporaryFillColor.slice(4, 6), 16);
});
});
}, 0);
+
return () => {
clearTimeout(timeout);
};
- }, [editShapeStyle, temporaryFillColor]);
+ }, [setShapeStyles, temporaryFillColor]);
const onReset = useCallback(() => {
- setTemporaryStrokeColor("000000");
- setTemporaryFillColor("ffffff");
- }, []);
+ setShapeStyles((shapes) => {
+ shapes.forEach((shape) => {
+ shape!["di:Style"]!["dmndi:FillColor"] ??= DEFAULT_FILL_COLOR;
+ shape!["di:Style"]!["dmndi:FillColor"]["@_red"] =
DEFAULT_FILL_COLOR["@_red"];
+ shape!["di:Style"]!["dmndi:FillColor"]["@_green"] =
DEFAULT_FILL_COLOR["@_green"];
+ shape!["di:Style"]!["dmndi:FillColor"]["@_blue"] =
DEFAULT_FILL_COLOR["@_blue"];
+
+ shape!["di:Style"]!["dmndi:StrokeColor"] ??= DEFAULT_STROKE_COLOR;
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_red"] =
DEFAULT_STROKE_COLOR["@_red"];
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_green"] =
DEFAULT_STROKE_COLOR["@_green"];
+ shape!["di:Style"]!["dmndi:StrokeColor"]["@_blue"] =
DEFAULT_STROKE_COLOR["@_blue"];
+ });
+ });
+ }, [setShapeStyles]);
const strokeColorPickerRef = React.useRef<HTMLInputElement>(null) as
React.MutableRefObject<HTMLInputElement>;
const fillColorPickerRef = React.useRef<HTMLInputElement>(null) as
React.MutableRefObject<HTMLInputElement>;
diff --git a/packages/dmn-editor/src/propertiesPanel/SingleNodeProperties.tsx
b/packages/dmn-editor/src/propertiesPanel/SingleNodeProperties.tsx
index cd258c487c5..12a5ccff7f6 100644
--- a/packages/dmn-editor/src/propertiesPanel/SingleNodeProperties.tsx
+++ b/packages/dmn-editor/src/propertiesPanel/SingleNodeProperties.tsx
@@ -56,6 +56,7 @@ export function SingleNodeProperties({ nodeId }: { nodeId:
string }) {
const { externalModelsByNamespace } = useExternalModels();
const node = useDmnEditorStore((s) =>
s.computed(s).getDiagramData(externalModelsByNamespace).nodesById.get(nodeId));
const [isSectionExpanded, setSectionExpanded] = useState<boolean>(true);
+ const nodeIds = useMemo(() => (node?.id ? [node.id] : []), [node?.id]);
if (!node) {
return <>Node not found: {nodeId}</>;
@@ -177,10 +178,10 @@ export function SingleNodeProperties({ nodeId }: {
nodeId: string }) {
</>
)}
- <FontOptions startExpanded={false} nodeIds={[node.id]} />
+ <FontOptions startExpanded={false} nodeIds={nodeIds} />
<ShapeOptions
startExpanded={false}
- nodeIds={[node.id]}
+ nodeIds={nodeIds}
isDimensioningEnabled={true}
isPositioningEnabled={true}
/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]