Skip to content

Commit

Permalink
[2615] Improve the useDropNode hook lifecycle
Browse files Browse the repository at this point in the history
Bug: #2615
Signed-off-by: Guillaume Coutable <guillaume.coutable@obeo.fr>
  • Loading branch information
gcoutable committed Nov 22, 2023
1 parent 7a6a17e commit 401a9ce
Show file tree
Hide file tree
Showing 20 changed files with 269 additions and 221 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.adoc
Expand Up @@ -70,6 +70,8 @@ It will currently provide the ability to customize the application icon and appl
The API of this component will also change over time so API breaks should be expected in the upcoming releases.
+
This new package and those new components are the first part of our work to make Sirius Web more reusable.
- https://github.com/eclipse-sirius/sirius-web/issues/2615[#2615] [diagram] `useDropNode().dropFeedbackStyleProvider` has been removed.
Use `useDropNodeStyle(node.id)` instead to get the feedback of the drop feedback.

=== Dependency update

Expand Down Expand Up @@ -107,6 +109,7 @@ It uses our algorithm instead of elk.js to perform the arrange-all.
- https://github.com/eclipse-sirius/sirius-web/issues/2591[#2591] [diagram] Give the right node descriptions to node convert handlers.
- https://github.com/eclipse-sirius/sirius-web/issues/2601[#2601] [emf] Fix an issue in `EditingContextCrossReferenceAdapter` where references to moved objects were lost.
- https://github.com/eclipse-sirius/sirius-web/issues/2582[#2582] [diagram] Fix a delay in renderer of palette tools between the one from _getPalette_ backend call and the one declared in frontend.
- https://github.com/eclipse-sirius/sirius-web/issues/2615[#2615] [diagram] Fix the `useDropNode` lifecycle.

=== New Features

Expand Down
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2023 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 React from 'react';
import { DiagramDescriptionContextValue } from './DiagramDescriptionContext.types';

const defaultValue: DiagramDescriptionContextValue = {
diagramDescription: null,
};

export const DiagramDescriptionContext = React.createContext<DiagramDescriptionContextValue>(defaultValue);
@@ -0,0 +1,18 @@
/*******************************************************************************
* Copyright (c) 2023 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 { GQLDiagramDescription } from '../representation/DiagramRepresentation.types';

export interface DiagramDescriptionContextValue {
diagramDescription: GQLDiagramDescription | null;
}
Expand Up @@ -11,12 +11,6 @@
* Obeo - initial API and implementation
*******************************************************************************/

export interface GQLDiagramDescription {
id: string;
nodeDescriptions: GQLNodeDescription[];
__typename: string;
}

export interface GQLNodeDescription {
id: string;
borderNodeDescriptions: GQLNodeDescription[];
Expand Down
Expand Up @@ -27,6 +27,7 @@ export { Label } from './renderer/Label';
export { useConnector } from './renderer/connector/useConnector';
export { useDrop } from './renderer/drop/useDrop';
export { useDropNode } from './renderer/dropNode/useDropNode';
export { useDropNodeStyle } from './renderer/dropNode/useDropNodeStyle';
export { ConnectionCreationHandles } from './renderer/handles/ConnectionCreationHandles';
export { ConnectionHandles } from './renderer/handles/ConnectionHandles';
export type { ConnectionHandle } from './renderer/handles/ConnectionHandles.types';
Expand Down
Expand Up @@ -27,6 +27,8 @@ import {
useEdgesState,
useNodesState,
} from 'reactflow';
import { DiagramDescriptionContext } from '../contexts/DiagramDescriptionContext';
import { DiagramDescriptionContextValue } from '../contexts/DiagramDescriptionContext.types';
import { NodeTypeContext } from '../contexts/NodeContext';
import { NodeTypeContextValue } from '../contexts/NodeContext.types';
import { convertDiagram } from '../converter/convertDiagram';
Expand All @@ -44,6 +46,8 @@ import { useInitialFitToScreen } from './fit-to-screen/useInitialFitToScreen';
import { useHandleChange } from './handles/useHandleChange';
import { RawDiagram } from './layout/layout.types';
import { useLayout } from './layout/useLayout';
import { NodeContext } from './node/NodeContext';
import { NodeContextValue } from './node/NodeContext.types';
import { DiagramNodeType } from './node/NodeTypes.types';
import { useNodeType } from './node/useNodeType';
import { DiagramPalette } from './palette/DiagramPalette';
Expand All @@ -55,17 +59,11 @@ import { useDiagramSelection } from './selection/useDiagramSelection';
import { useSnapToGrid } from './snap-to-grid/useSnapToGrid';

import 'reactflow/dist/style.css';
import { NodeContext } from './node/NodeContext';
import { NodeContextValue } from './node/NodeContext.types';

const GRID_STEP: number = 10;

export const DiagramRenderer = ({
diagramRefreshedEventPayload,
diagramDescription,
selection,
setSelection,
}: DiagramRendererProps) => {
export const DiagramRenderer = ({ diagramRefreshedEventPayload, selection, setSelection }: DiagramRendererProps) => {
const { diagramDescription } = useContext<DiagramDescriptionContextValue>(DiagramDescriptionContext);
const { onDirectEdit } = useDiagramDirectEdit();
const { onDelete } = useDiagramDelete();

Expand All @@ -92,7 +90,7 @@ export const DiagramRenderer = ({
const convertedDiagram: Diagram = convertDiagram(
diagram,
nodeConverterHandlers,
diagramDescription.nodeDescriptions
diagramDescription?.nodeDescriptions ?? []
);

const previousDiagram: RawDiagram = {
Expand Down Expand Up @@ -147,9 +145,9 @@ export const DiagramRenderer = ({

const { snapToGrid, onSnapToGrid } = useSnapToGrid();

const { onNodeDragStart, onNodeDrag, onNodeDragStop, dropFeedbackStyleProvider } = useDropNode();
const { onNodeDragStart, onNodeDrag, onNodeDragStop, diagramBackgroundStyle } = useDropNode();
const { backgroundColor, smallGridColor, largeGridColor } = diagramBackgroundStyle;
const { setHoveredNode } = useContext<NodeContextValue>(NodeContext);
const { backgroundColor, smallGridColor, largeGridColor } = dropFeedbackStyleProvider.getDiagramBackgroundStyle();

return (
<ReactFlow
Expand Down
Expand Up @@ -13,15 +13,14 @@

import { Selection } from '@eclipse-sirius/sirius-components-core';
import { Edge, Node } from 'reactflow';
import { GQLDiagramDescription, GQLNodeDescription } from '../graphql/query/nodeDescriptionFragment.types';
import { GQLNodeDescription } from '../graphql/query/nodeDescriptionFragment.types';
import { GQLDiagramRefreshedEventPayload } from '../graphql/subscription/diagramEventSubscription.types';
import { MultiLabelEdgeData } from './edge/MultiLabelEdge.types';
import { ConnectionHandle } from './handles/ConnectionHandles.types';
import { DiagramNodeType } from './node/NodeTypes.types';

export interface DiagramRendererProps {
diagramRefreshedEventPayload: GQLDiagramRefreshedEventPayload;
diagramDescription: GQLDiagramDescription;
selection: Selection;
setSelection: (selection: Selection) => void;
}
Expand Down
Expand Up @@ -12,23 +12,49 @@
*******************************************************************************/

import React, { useState } from 'react';
import { DropNodeContextProviderProps, DropNodeContextValue } from './DropNodeContext.types';
import { NodeDropData } from './useDropNode.types';
import { DropNodeContextProviderProps, DropNodeContextValue, NodeDropData } from './DropNodeContext.types';

const defaultValue: DropNodeContextValue = {
dropData: {
initialParentId: null,
draggedNodeId: null,
targetNodeId: null,
compatibleNodeIds: [],
droppableOnDiagram: false,
},
initialParentId: null,
draggedNode: null,
targetNodeId: null,
compatibleNodeIds: [],
droppableOnDiagram: false,
setDropData: () => {},
setTargetNodeId: () => {},
};

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

export const DropNodeContextProvider = ({ children }: DropNodeContextProviderProps) => {
const [dropData, setDropData] = useState<NodeDropData>(defaultValue.dropData);
return <DropNodeContext.Provider value={{ dropData, setDropData }}>{children}</DropNodeContext.Provider>;
const [state, setState] = useState<NodeDropData>({
initialParentId: null,
draggedNode: null,
targetNodeId: null,
compatibleNodeIds: [],
droppableOnDiagram: false,
});

const setDropData = (dropData: NodeDropData) => {
setState((prevState) => ({ ...prevState, ...dropData }));
};

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

return (
<DropNodeContext.Provider
value={{
initialParentId: state.initialParentId,
draggedNode: state.draggedNode,
targetNodeId: state.targetNodeId,
compatibleNodeIds: state.compatibleNodeIds,
droppableOnDiagram: state.droppableOnDiagram,
setDropData,
setTargetNodeId,
}}>
{children}
</DropNodeContext.Provider>
);
};
Expand Up @@ -11,13 +11,22 @@
* Obeo - initial API and implementation
*******************************************************************************/

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

export type DropNodeContextValue = {
dropData: NodeDropData;
export type DropNodeContextValue = NodeDropData & {
setDropData: (newDropData: NodeDropData) => void;
setTargetNodeId: (targetNodeId: string | null) => void;
};

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

export interface DropNodeContextProviderProps {
children: React.ReactNode;
}

0 comments on commit 401a9ce

Please sign in to comment.