Skip to content

Commit

Permalink
[3435] Extract diagram style from useDropNode
Browse files Browse the repository at this point in the history
Bug: #3435
Signed-off-by: Michaël Charfadi <michael.charfadi@obeosoft.com>
  • Loading branch information
mcharfadi committed Apr 30, 2024
1 parent b8ead13 commit b9014e5
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 147 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Expand Up @@ -138,6 +138,7 @@ They still support returning an `java.time.Instant` object directly.
- https://github.com/eclipse-sirius/sirius-web/issues/3279[#3279] [core] Image URLs are now sanitized in a similar manner in all datafetchers, as a result absolute URLs to external images are better supported and a leading slash is now required anymore.
- https://github.com/eclipse-sirius/sirius-web/issues/3296[#3296] [diagram] Add a hook `useStore` to retrieve local `setNodes`, `setEdges`, `onEdgesChange` and `onNodesChange`, this hook is used to align how nodes and edges are manipulated during processing of ReactFlow events.
- https://github.com/eclipse-sirius/sirius-web/issues/3397[#3397] [diagram] Add helper lines when resizing nodes
- https://github.com/eclipse-sirius/sirius-web/issues/3435[#3435] [diagram] Extract diagram style from useDropNode

== v2024.3.0

Expand Down
Expand Up @@ -12,7 +12,7 @@
*******************************************************************************/

import { Selection, useSelection } from '@eclipse-sirius/sirius-components-core';
import React, { MouseEvent as ReactMouseEvent, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
import React, { MouseEvent as ReactMouseEvent, memo, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
import {
Background,
BackgroundVariant,
Expand Down Expand Up @@ -43,6 +43,7 @@ import { DebugPanel } from './debug/DebugPanel';
import { useDiagramDelete } from './delete/useDiagramDelete';
import { useDiagramDirectEdit } from './direct-edit/useDiagramDirectEdit';
import { useDrop } from './drop/useDrop';
import { useDropDiagramStyle } from './dropNode/useDropDiagramStyle';
import { useDropNode } from './dropNode/useDropNode';
import { ConnectionLine } from './edge/ConnectionLine';
import { edgeTypes } from './edge/EdgeTypes';
Expand Down Expand Up @@ -75,7 +76,7 @@ import 'reactflow/dist/style.css';

const GRID_STEP: number = 10;

export const DiagramRenderer = ({ diagramRefreshedEventPayload }: DiagramRendererProps) => {
export const DiagramRenderer = memo(({ diagramRefreshedEventPayload }: DiagramRendererProps) => {
const { readOnly } = useContext<DiagramContextValue>(DiagramContext);
const { diagramDescription } = useDiagramDescription();
const { getEdges, onEdgesChange, getNodes, setEdges, setNodes } = useStore();
Expand Down Expand Up @@ -111,7 +112,8 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload }: DiagramRendere
const { onConnect, onConnectStart, onConnectEnd } = useConnector();
const { reconnectEdge } = useReconnectEdge();
const { onDrop, onDragOver } = useDrop();
const { onNodeDragStart, onNodeDrag, onNodeDragStop, diagramBackgroundStyle } = useDropNode();
const { onNodeDragStart, onNodeDrag, onNodeDragStop } = useDropNode();
const { backgroundColor, largeGridColor, smallGridColor } = useDropDiagramStyle();
const { nodeTypes } = useNodeType();

const { nodeConverters } = useContext<NodeTypeContextValue>(NodeTypeContext);
Expand Down Expand Up @@ -174,10 +176,12 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload }: DiagramRendere
const handleNodesChange: OnNodesChange = useCallback(
(changes: NodeChange[]) => {
const noReadOnlyChanges = filterReadOnlyChanges(changes);
const isResetChange = changes.find((change) => change.type === 'reset');
if (
noReadOnlyChanges.length === 1 &&
noReadOnlyChanges[0]?.type === 'dimensions' &&
typeof noReadOnlyChanges[0].resizing !== 'boolean'
isResetChange ||
(noReadOnlyChanges.length === 1 &&
noReadOnlyChanges[0]?.type === 'dimensions' &&
typeof noReadOnlyChanges[0].resizing !== 'boolean')
) {
setNodes((oldNodes) => applyNodeChanges(noReadOnlyChanges, oldNodes));
} else {
Expand Down Expand Up @@ -238,8 +242,6 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload }: DiagramRendere

const { snapToGrid, onSnapToGrid } = useSnapToGrid();

const { backgroundColor, smallGridColor, largeGridColor } = diagramBackgroundStyle;

const closeAllPalettes = useCallback(() => {
hideDiagramPalette();
hideDiagramElementPalette();
Expand Down Expand Up @@ -359,4 +361,4 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload }: DiagramRendere
{helperLinesEnabled ? <HelperLines horizontal={horizontalHelperLine} vertical={verticalHelperLine} /> : null}
</ReactFlow>
);
};
});
Expand Up @@ -15,56 +15,38 @@ import React, { useState } from 'react';
import { DropNodeContextProviderProps, DropNodeContextState, DropNodeContextValue } from './DropNodeContext.types';

const defaultValue: DropNodeContextValue = {
initialParentId: null,
draggedNode: null,
targetNodeId: null,
compatibleNodeIds: [],
initialPosition: null,
initialPositionAbsolute: null,
droppableOnDiagram: false,
initializeDrop: () => {},
setTargetNodeId: () => {},
resetDrop: () => {},
};

export const DropNodeContext = React.createContext<DropNodeContextValue>(defaultValue);

export const DropNodeContextProvider = ({ children }: DropNodeContextProviderProps) => {
const [state, setState] = useState<DropNodeContextState>({
initialParentId: null,
draggedNode: null,
targetNodeId: null,
compatibleNodeIds: [],
droppableOnDiagram: false,
});
const [state, setState] = useState<DropNodeContextState>(defaultValue);

const initializeDrop = (dropData: DropNodeContextState) => {
setState((prevState) => ({ ...prevState, ...dropData }));
};

const setTargetNodeId = (targetNodeId: string | null) => {
setState((prevState) => ({ ...prevState, targetNodeId }));
};

const resetDrop = () => {
setState((prevState) => ({
...prevState,
initialParentId: null,
draggedNode: null,
targetNodeId: null,
initialPosition: null,
initialPositionAbsolute: null,
droppableOnDiagram: false,
compatibleNodeIds: [],
}));
};

return (
<DropNodeContext.Provider
value={{
initialParentId: state.initialParentId,
draggedNode: state.draggedNode,
targetNodeId: state.targetNodeId,
compatibleNodeIds: state.compatibleNodeIds,
initialPosition: state.initialPosition,
initialPositionAbsolute: state.initialPositionAbsolute,
droppableOnDiagram: state.droppableOnDiagram,
initializeDrop,
setTargetNodeId,
resetDrop,
}}>
{children}
Expand Down
Expand Up @@ -11,20 +11,16 @@
* Obeo - initial API and implementation
*******************************************************************************/

import { Node } from 'reactflow';
import { NodeData } from '../DiagramRenderer.types';
import { XYPosition } from 'reactflow';

export type DropNodeContextValue = DropNodeContextState & {
initializeDrop: (newDropData: DropNodeContextState) => void;
setTargetNodeId: (targetNodeId: string | null) => void;
resetDrop: () => void;
};

export interface DropNodeContextState {
initialParentId: string | null;
draggedNode: Node<NodeData> | null;
targetNodeId: string | null;
compatibleNodeIds: string[];
initialPosition: XYPosition | null;
initialPositionAbsolute: XYPosition | null;
droppableOnDiagram: boolean;
}

Expand Down
@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/

import { useTheme } from '@material-ui/core/styles';
import { useContext } from 'react';
import { useReactFlow } from 'reactflow';
import { EdgeData, NodeData } from '../DiagramRenderer.types';
import { DropNodeContext } from './DropNodeContext';
import { DropNodeContextValue } from './DropNodeContext.types';
import { useDropDiagramStyleValue } from './useDropDiagramStyle.types';

export const useDropDiagramStyle = (): useDropDiagramStyleValue => {
const { droppableOnDiagram } = useContext<DropNodeContextValue>(DropNodeContext);
const { getNodes } = useReactFlow<NodeData, EdgeData>();
const theme = useTheme();

const targetNode = getNodes().find((node) => node.data.isDropNodeTarget);
const draggedNode = getNodes().find((node) => node.dragging);

const diagramTargeted: boolean = !targetNode && !!draggedNode?.parentNode;
const diagramForbidden: boolean = diagramTargeted && !!draggedNode?.id !== null && !droppableOnDiagram;
const backgroundColor = diagramForbidden ? theme.palette.action.disabledBackground : theme.palette.background.default;

return {
backgroundColor,
smallGridColor: diagramForbidden ? backgroundColor : '#f1f1f1',
largeGridColor: diagramForbidden ? backgroundColor : '#cccccc',
};
};
@@ -0,0 +1,18 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/

export interface useDropDiagramStyleValue {
backgroundColor: string;
smallGridColor: string;
largeGridColor: string;
}

0 comments on commit b9014e5

Please sign in to comment.