From 2a9ca7f144b1ca115b4c8a48db3ffc64409083f0 Mon Sep 17 00:00:00 2001 From: Michael Charfadi Date: Tue, 17 Dec 2024 15:08:37 +0100 Subject: [PATCH] [4323] Improve palette style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://github.com/eclipse-sirius/sirius-web/issues/4323 Signed-off-by: Michaƫl Charfadi --- CHANGELOG.adoc | 1 + .../direct-edit/useDiagramDirectEdit.tsx | 2 +- .../src/renderer/palette/Palette.tsx | 54 ++++++++++--------- .../PaletteQuickAccessToolBar.tsx | 35 ++++++------ .../tool-list/PaletteToolSectionList.tsx | 3 +- .../src/renderer/palette/usePalette.tsx | 2 +- .../src/renderer/panel/DiagramPanel.tsx | 18 ++++++- 7 files changed, 68 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f0e85f2edd..c02da7f87a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -158,6 +158,7 @@ Note that you may need to encode special characters like `[`(by `%5B`) and `]` ( - https://github.com/eclipse-sirius/sirius-web/issues/4474[#4474] [query] Add EMF Services (eSet, eUnset) for the Query View. - https://github.com/eclipse-sirius/sirius-web/issues/4354[#4354] [table] Add support for cursor based pagination in table view DSL - https://github.com/eclipse-sirius/sirius-web/issues/4478[#4478] [sirius-web] Provide an API to search custom resource on download document action +- https://github.com/eclipse-sirius/sirius-web/issues/4323[#4323] [diagram] The palette can now be smaller and have an arrow to close it == v2025.1.0 diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/direct-edit/useDiagramDirectEdit.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/direct-edit/useDiagramDirectEdit.tsx index 9f43e3fb6b..df76ca8d6b 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/direct-edit/useDiagramDirectEdit.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/direct-edit/useDiagramDirectEdit.tsx @@ -41,7 +41,7 @@ export const useDiagramDirectEdit = (): UseDiagramDirectEditValue => { if (key !== 'F2' && isTextField) { return; } - + event.preventDefault(); const validFirstInputChar = !event.metaKey && !event.ctrlKey && key.length === 1 && directEditActivationValidCharacters.test(key); diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx index 6ac7064da2..09b7bd5c32 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx @@ -11,16 +11,17 @@ * Obeo - initial API and implementation *******************************************************************************/ +import CloseIcon from '@mui/icons-material/Close'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import Box from '@mui/material/Box'; import Divider from '@mui/material/Divider'; +import IconButton from '@mui/material/IconButton'; import Paper from '@mui/material/Paper'; import { Edge, Node, useStoreApi, useViewport, XYPosition } from '@xyflow/react'; import React, { useCallback, useEffect, useState } from 'react'; import Draggable, { DraggableData } from 'react-draggable'; import { makeStyles } from 'tss-react/mui'; import { EdgeData, NodeData } from '../DiagramRenderer.types'; -import { useGroupPalette } from './group-tool/useGroupPalette'; import { GQLPalette, GQLPaletteDivider, @@ -48,14 +49,13 @@ const usePaletteStyle = makeStyles()((theme, props) => ({ zIndex: 5, position: 'fixed', width: props.paletteWidth, - height: props.paletteHeight, }, paletteHeader: { cursor: 'move', width: '100%', display: 'flex', flexDirection: 'row', - justifyContent: 'flex-start', + justifyContent: 'space-between', alignItems: 'center', backgroundColor: `${theme.palette.secondary.main}08`, }, @@ -77,7 +77,6 @@ const computeDraggableBounds = (bounds?: DOMRect): XYPosition => { }; const paletteWidth = 200; -const paletteHeight = 275; const getPaletteToolCount = (palette: GQLPalette): number => { return ( @@ -93,7 +92,8 @@ const computePaletteLocation = ( paletteX: number, paletteY: number, viewportWidth: number, - viewportHeight: number + viewportHeight: number, + paletteHeight: number ): XYPosition => { return { x: paletteX + paletteWidth < viewportWidth ? paletteX : viewportWidth - paletteWidth, @@ -126,9 +126,16 @@ export const Palette = ({ y = (paletteY - viewportY) / viewportZoom; } const { handleToolClick, palette } = usePalette({ x, y, diagramElementId, onDirectEditClick, targetObjectId }); + const paletteHeight = palette ? palette.paletteEntries.length * 30 + 50 : 50; useEffect(() => { - const paletteLocation: XYPosition = computePaletteLocation(paletteX, paletteY, viewportWidth, viewportHeight); + const paletteLocation: XYPosition = computePaletteLocation( + paletteX, + paletteY, + viewportWidth, + viewportHeight, + paletteHeight + ); setState((prevState) => ({ ...prevState, controlledPosition: paletteLocation })); }, [paletteX, paletteY, viewportWidth, viewportHeight]); @@ -138,36 +145,32 @@ export const Palette = ({ const { hideDiagramPalette } = useDiagramPalette(); const { hideDiagramElementPalette } = useDiagramElementPalette(); - const { hideGroupPalette } = useGroupPalette(); + const store = useStoreApi, Edge>(); const closeAllPalettes = useCallback(() => { hideDiagramPalette(); hideDiagramElementPalette(); - hideGroupPalette(); - }, [hideDiagramPalette, hideDiagramElementPalette, hideGroupPalette]); - const store = useStoreApi, Edge>(); + //Set the focus from the palette to the node/edge + const selectedNode = store.getState().nodes.filter((node) => node.selected); + const selectedEdges = store.getState().edges.filter((edge) => edge.selected); + if (selectedNode.length + selectedEdges.length === 1) { + const selectedElement = selectedNode[0] || selectedEdges[0]; + if (selectedElement) { + let domElement = document.querySelector(`[data-id='${selectedElement.id}']`); + if (domElement) { + (domElement as HTMLElement).focus(); + } + } + } + }, [hideDiagramPalette, hideDiagramElementPalette]); const onKeyDown = useCallback((event: React.KeyboardEvent) => { const { key } = event; if (key === 'Escape') { // Stop propagating the event in order to keep the node/edge selected event.stopPropagation(); - closeAllPalettes(); - - //Set the focus from the palette to the node/edge - const selectedNode = store.getState().nodes.filter((node) => node.selected); - const selectedEdges = store.getState().edges.filter((edge) => edge.selected); - if (selectedNode.length + selectedEdges.length === 1) { - const selectedElement = selectedNode[0] || selectedEdges[0]; - if (selectedElement) { - let domElement = document.querySelector(`[data-id='${selectedElement.id}']`); - if (domElement) { - (domElement as HTMLElement).focus(); - } - } - } } }, []); @@ -209,6 +212,9 @@ export const Palette = ({ tabIndex={0}> + + + | Edge): diagramEle return !!diagramElement.data && 'bendingPoints' in diagramElement.data && !!diagramElement.data.bendingPoints; }; -const useStyle = makeStyles()(() => ({ +const useStyle = makeStyles()((theme) => ({ quickAccessTools: { display: 'flex', flexWrap: 'nowrap', @@ -44,6 +43,9 @@ const useStyle = makeStyles()(() => ({ alignItems: 'center', overflowX: 'auto', }, + quickAccessToolContainer: { + width: theme.spacing(3.5), + }, })); export const PaletteQuickAccessToolBar = ({ @@ -54,15 +56,10 @@ export const PaletteQuickAccessToolBar = ({ y, }: PaletteQuickAccessToolBarProps) => { const { classes } = useStyle(); - + const quickAccessToolComponents: JSX.Element[] = []; const { nodeLookup, edgeLookup } = useStoreApi, Edge>().getState(); const diagramElement = nodeLookup.get(diagramElementId) || edgeLookup.get(diagramElementId); - const quickAccessToolComponents: JSX.Element[] = []; - quickAccessTools.forEach((tool) => - quickAccessToolComponents.push() - ); - if (diagramElement) { if (isPinnable(diagramElement)) { quickAccessToolComponents.push( @@ -109,16 +106,18 @@ export const PaletteQuickAccessToolBar = ({ /> ) ); - } - if (quickAccessToolComponents.length > 0) { - return ( - <> - {quickAccessToolComponents} - - + quickAccessTools.forEach((tool) => + quickAccessToolComponents.push() ); - } else { - return null; } + return ( + + {quickAccessToolComponents.map((quickAcessTool, index) => ( +
+ {quickAcessTool} +
+ ))} +
+ ); }; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/tool-list/PaletteToolSectionList.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/tool-list/PaletteToolSectionList.tsx index 7caf25d95f..9dd912db9c 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/tool-list/PaletteToolSectionList.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/tool-list/PaletteToolSectionList.tsx @@ -16,6 +16,7 @@ import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import Tooltip from '@mui/material/Tooltip'; import { makeStyles } from 'tss-react/mui'; +import { isSingleClickOnDiagramElementTool } from '../Palette'; import { ToolListItem } from '../tool-list-item/ToolListItem'; import { PaletteToolSectionListProps } from './PaletteToolSectionList.types'; @@ -69,7 +70,7 @@ export const PaletteToolSectionList = ({ toolSection, onToolClick, onBackToMainL - {toolSection.tools.map((tool) => ( + {toolSection.tools.filter(isSingleClickOnDiagramElementTool).map((tool) => ( ))} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/usePalette.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/usePalette.tsx index e364eb5522..ec9375224c 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/usePalette.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/usePalette.tsx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 2025 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 diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx index dddcda3321..9bef364df6 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx @@ -28,7 +28,7 @@ import IconButton from '@mui/material/IconButton'; import Paper from '@mui/material/Paper'; import Tooltip from '@mui/material/Tooltip'; import { Edge, Node, Panel, useNodesInitialized, useReactFlow } from '@xyflow/react'; -import { memo, useContext, useEffect, useState } from 'react'; +import { memo, useCallback, useContext, useEffect, useState } from 'react'; import { DiagramContext } from '../../contexts/DiagramContext'; import { DiagramContextValue } from '../../contexts/DiagramContext.types'; import { HelperLinesIcon } from '../../icons/HelperLinesIcon'; @@ -41,6 +41,9 @@ import { useFadeDiagramElements } from '../fade/useFadeDiagramElements'; import { useFullscreen } from '../fullscreen/useFullscreen'; import { useHideDiagramElements } from '../hide/useHideDiagramElements'; import { useArrangeAll } from '../layout/useArrangeAll'; +import { useGroupPalette } from '../palette/group-tool/useGroupPalette'; +import { useDiagramElementPalette } from '../palette/useDiagramElementPalette'; +import { useDiagramPalette } from '../palette/useDiagramPalette'; import { usePinDiagramElements } from '../pin/usePinDiagramElements'; import { DiagramPanelActionProps, DiagramPanelProps, DiagramPanelState } from './DiagramPanel.types'; import { diagramPanelActionExtensionPoint } from './DiagramPanelExtensionPoints'; @@ -68,6 +71,15 @@ export const DiagramPanel = memo( ); const { getNodes, getEdges, zoomIn, zoomOut, fitView } = useReactFlow, Edge>(); + const { hideDiagramPalette } = useDiagramPalette(); + const { hideDiagramElementPalette } = useDiagramElementPalette(); + const { hideGroupPalette } = useGroupPalette(); + + const closeAllPalettes = useCallback(() => { + hideDiagramPalette(); + hideDiagramElementPalette(); + hideGroupPalette(); + }, [hideDiagramPalette, hideDiagramElementPalette, hideGroupPalette]); const getAllElementsIds = () => [...getNodes().map((elem) => elem.id), ...getEdges().map((elem) => elem.id)]; const getSelectedNodes = () => getNodes().filter((node) => node.selected); @@ -266,7 +278,9 @@ export const DiagramPanel = memo( {diagramPanelActionComponents.map(({ Component: DiagramPanelActionComponent }, index) => ( - +
+ +
))}