Skip to content

Commit

Permalink
[3981] Convert the GroupPalette to the new Palette
Browse files Browse the repository at this point in the history
Bug: #3981
Signed-off-by: Florian Barbin <[email protected]>
  • Loading branch information
florianbarbin committed Oct 15, 2024
1 parent a42f620 commit 2f68f6f
Show file tree
Hide file tree
Showing 19 changed files with 392 additions and 324 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,74 +12,35 @@
*******************************************************************************/

import { DataExtension, useData } from '@eclipse-sirius/sirius-components-core';
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
import Box from '@mui/material/Box';
import Divider from '@mui/material/Divider';
import Paper from '@mui/material/Paper';
import { Edge, Node, useReactFlow, useStoreApi, useViewport, XYPosition } from '@xyflow/react';
import React, { useEffect, useState } from 'react';
import Draggable, { DraggableData } from 'react-draggable';
import { makeStyles } from 'tss-react/mui';
import { Edge, Node, useReactFlow, useViewport } from '@xyflow/react';
import React from 'react';
import { EdgeData, NodeData } from '../DiagramRenderer.types';
import {
DiagramPaletteToolContributionComponentProps,
DiagramPaletteToolContributionProps,
} from './DiagramPaletteToolContribution.types';
import { DraggablePalette } from './draggable-palette/DraggablePalette';
import { PaletteEntry, ToolSection } from './draggable-palette/DraggablePalette.types';
import {
GQLPaletteDivider,
GQLPaletteEntry,
GQLSingleClickOnDiagramElementTool,
GQLToolSection,
PaletteProps,
PaletteStyleProps,
} from './Palette.types';
import { PaletteSearchField } from './searchField/PaletteSearchField';
import { PaletteSearchResult } from './tool-list/PaletteSearchResult';
import { PaletteToolList } from './tool-list/PaletteToolList';
import { usePaletteQuickAccessToolBar } from './tool-list/usePaletteQuickAccessToolBar';
import { diagramPaletteToolExtensionPoint } from './tool/DiagramPaletteToolExtensionPoints';
import { useDiagramPalette } from './useDiagramPalette';
import { usePalette } from './usePalette';

const usePaletteStyle = makeStyles<PaletteStyleProps>()((theme, props) => ({
palette: {
display: 'grid',
gridAutoRows: `fit-content(100%)`,
border: `1px solid ${theme.palette.divider}`,
borderRadius: '10px',
zIndex: 5,
position: 'fixed',
width: props.paletteWidth,
height: props.paletteHeight,
},
paletteHeader: {
cursor: 'move',
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
color: theme.palette.grey[400],
},
}));

export const isSingleClickOnDiagramElementTool = (tool: GQLPaletteEntry): tool is GQLSingleClickOnDiagramElementTool =>
tool.__typename === 'SingleClickOnDiagramElementTool';

export const isToolSection = (entry: GQLPaletteEntry): entry is GQLToolSection => entry.__typename === 'ToolSection';

export const isPaletteDivider = (entry: GQLPaletteDivider): entry is GQLToolSection =>
export const isPaletteDivider = (entry: GQLPaletteEntry): entry is GQLPaletteDivider =>
entry.__typename === 'PaletteDivider';

const computeDraggableBounds = (bounds?: DOMRect): XYPosition => {
return {
x: bounds?.width ?? 0,
y: bounds?.height ?? 0,
};
};

const paletteWidth = 200;
const paletteHeight = 275;

export const Palette = ({
x: paletteX,
y: paletteY,
Expand All @@ -90,11 +51,7 @@ export const Palette = ({
onEscape,
}: PaletteProps) => {
const { getNodes } = useReactFlow<Node<NodeData>, Edge<EdgeData>>();
const [searchToolValue, setSearchToolValue] = useState<string>('');
const { domNode } = useStoreApi().getState();
const { x: viewportWidth, y: viewportHeight } = computeDraggableBounds(domNode?.getBoundingClientRect());

const [controlledPosition, setControlledPosition] = useState<XYPosition>({ x: 0, y: 0 });
let x: number = 0;
let y: number = 0;
const { x: viewportX, y: viewportY, zoom: viewportZoom } = useViewport();
Expand All @@ -103,10 +60,6 @@ export const Palette = ({
y = (paletteY - viewportY) / viewportZoom;
}
const { handleToolClick, palette } = usePalette({ x, y, diagramElementId, onDirectEditClick, targetObjectId });
useEffect(() => {
const paletteLocation: XYPosition = computePaletteLocation(paletteX, paletteY, viewportWidth, viewportHeight);
setControlledPosition(paletteLocation);
}, [paletteX, paletteY, viewportWidth, viewportHeight]);

const paletteToolData: DataExtension<DiagramPaletteToolContributionProps[]> = useData(
diagramPaletteToolExtensionPoint
Expand All @@ -117,20 +70,9 @@ export const Palette = ({
const paletteToolComponents: React.ComponentType<DiagramPaletteToolContributionComponentProps>[] = node
? paletteToolData.data.filter((data) => data.canHandle(node)).map((data) => data.component)
: [];
const paletteEntries: PaletteEntry[] = palette ? filterSingleClickOnDiagramElementTool(palette?.paletteEntries) : [];

const toolCount =
(palette
? palette.paletteEntries.filter(isSingleClickOnDiagramElementTool).length +
palette.quickAccessTools.filter(isSingleClickOnDiagramElementTool).length +
palette.paletteEntries
.filter(isToolSection)
.filter((toolSection) => toolSection.tools.filter(isSingleClickOnDiagramElementTool).length > 0).length
: 0) +
(hideableDiagramElement ? (node ? 3 : 1) : 0) +
paletteToolComponents.length;
const { classes } = usePaletteStyle({ paletteWidth: `${paletteWidth}px`, paletteHeight: `${paletteHeight}px` });

const { element } = usePaletteQuickAccessToolBar({
const { quickAccessToolComponents } = usePaletteQuickAccessToolBar({
diagramElementId: diagramElementId,
onToolClick: handleToolClick,
node,
Expand All @@ -141,73 +83,45 @@ export const Palette = ({
hideableDiagramElement,
});

const toolCount = paletteEntries.length + quickAccessToolComponents.length;

const { getLastToolInvoked } = useDiagramPalette();
const lastToolInvoked = palette ? getLastToolInvoked(palette.id) : null;
const lastSingleClickOnDiagramElementToolInvoked =
lastToolInvoked && isSingleClickOnDiagramElementTool(lastToolInvoked) ? lastToolInvoked : null;
const shouldRender = palette && (node || (!node && toolCount > 0));
if (!shouldRender) {
return null;
}

const onPaletteDragStop = (_event, data: DraggableData) => {
setControlledPosition(data);
};

const onSearchFieldValueChanged = (newValue: string): void => {
setSearchToolValue(newValue);
};
// If running in React Strict mode, ReactDOM.findDOMNode() is deprecated.
// Unfortunately, in order for <Draggable> to work properly, it needs raw access
// to the underlying DOM node. To avoid the warning, we pass a `nodeRef`

const nodeRef = React.createRef<HTMLDivElement>();
const draggableBounds = {
left: 0,
top: 0,
bottom: viewportHeight - paletteHeight,
right: viewportWidth - paletteWidth,
};

const paletteQuickAccessToolBar = element ? (
<>
{element} <Divider />
</>
) : null;

return (
<Draggable
nodeRef={nodeRef}
bounds={draggableBounds}
handle="#tool-palette-header"
position={controlledPosition}
onStop={onPaletteDragStop}>
<Paper
ref={nodeRef}
className={classes.palette}
data-testid="Palette"
elevation={3}
onClick={(event) => event.stopPropagation()}>
<Box id="tool-palette-header" className={classes.paletteHeader}>
<DragIndicatorIcon />
</Box>
<Divider />
{paletteQuickAccessToolBar}
<PaletteSearchField onValueChanged={onSearchFieldValueChanged} onEscape={onEscape} />
<Divider />
{searchToolValue.length > 0 ? (
<PaletteSearchResult searchToolValue={searchToolValue} palette={palette} onToolClick={handleToolClick} />
) : (
<PaletteToolList palette={palette} onToolClick={handleToolClick} />
)}
</Paper>
</Draggable>
<DraggablePalette
x={paletteX}
y={paletteY}
onToolClick={handleToolClick}
paletteEntries={paletteEntries}
quickAccessToolComponents={quickAccessToolComponents}
lastToolInvoked={lastSingleClickOnDiagramElementToolInvoked}
onEscape={onEscape}
/>
);
};
const computePaletteLocation = (
paletteX: number,
paletteY: number,
viewportWidth: number,
viewportHeight: number
): XYPosition => {
return {
x: paletteX + paletteWidth < viewportWidth ? paletteX : viewportWidth - paletteWidth,
y: paletteY + paletteHeight < viewportHeight ? paletteY : viewportHeight - paletteHeight,
};
const filterSingleClickOnDiagramElementTool = (paletteEntries: GQLPaletteEntry[]): PaletteEntry[] => {
const filteredPaletteEntries: PaletteEntry[] = [];
paletteEntries.forEach((paletteEntry) => {
if (isSingleClickOnDiagramElementTool(paletteEntry) || isPaletteDivider(paletteEntry)) {
filteredPaletteEntries.push(paletteEntry);
} else if (isToolSection(paletteEntry)) {
const currentToolSection = paletteEntry as GQLToolSection;
const filteredTools = currentToolSection.tools.filter(isSingleClickOnDiagramElementTool);
if (filteredTools.length > 0) {
const filteredToolSection: ToolSection = {
...currentToolSection,
tools: filteredTools,
__typename: 'ToolSection',
};
filteredPaletteEntries.push(filteredToolSection);
}
}
});
return filteredPaletteEntries;
};
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ export interface PaletteStyleProps {
export interface GQLTool extends GQLPaletteEntry {
label: string;
iconURL: string[];
__typename: string;
}

export interface GQLSingleClickOnDiagramElementTool extends GQLTool {
appliesToDiagramRoot: boolean;
dialogDescriptionId: string;
__typename: 'SingleClickOnDiagramElementTool';
}

export interface GQLPalette {
Expand Down
Loading

0 comments on commit 2f68f6f

Please sign in to comment.