From bdafde987bfe1033202354b91463650f4bd04125 Mon Sep 17 00:00:00 2001 From: aamanrebello Date: Sun, 12 Jan 2025 14:15:13 +0000 Subject: [PATCH] Introduce zoom control with tentative UI --- calm-visualizer/src/App.tsx | 31 ++++++++++--------- .../cytoscape-renderer/CytoscapeRenderer.tsx | 22 +++++++++++-- .../src/components/navbar/Navbar.css | 8 +++++ .../src/components/navbar/Navbar.tsx | 28 +++++++++++++++-- .../src/components/zoom-context.provider.tsx | 28 +++++++++++++++++ 5 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 calm-visualizer/src/components/navbar/Navbar.css create mode 100644 calm-visualizer/src/components/zoom-context.provider.tsx diff --git a/calm-visualizer/src/App.tsx b/calm-visualizer/src/App.tsx index e397a430..01155cb0 100644 --- a/calm-visualizer/src/App.tsx +++ b/calm-visualizer/src/App.tsx @@ -4,6 +4,7 @@ import Drawer from './components/drawer/Drawer'; import Navbar from './components/navbar/Navbar'; import { CALMInstantiation } from '../../shared/src/types'; import React from 'react'; +import { ZoomProvider } from './components/zoom-context.provider'; function App() { const [title, setTitle] = useState(undefined); @@ -21,20 +22,22 @@ function App() { } return ( -
- setNodeDescActive((isNodeDescActive) => !isNodeDescActive)} - toggleConnectionDesc={() => setConDescActive((isConDescActive) => !isConDescActive)} - /> - -
+ +
+ setNodeDescActive((isNodeDescActive) => !isNodeDescActive)} + toggleConnectionDesc={() => setConDescActive((isConDescActive) => !isConDescActive)} + /> + +
+
); } diff --git a/calm-visualizer/src/components/cytoscape-renderer/CytoscapeRenderer.tsx b/calm-visualizer/src/components/cytoscape-renderer/CytoscapeRenderer.tsx index 87b7bf9d..54f84ca6 100644 --- a/calm-visualizer/src/components/cytoscape-renderer/CytoscapeRenderer.tsx +++ b/calm-visualizer/src/components/cytoscape-renderer/CytoscapeRenderer.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import './cytoscape.css'; -import { useEffect, useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import cytoscape, { Core, EdgeSingular, NodeSingular } from 'cytoscape'; import nodeHtmlLabel from 'cytoscape-node-html-label'; import nodeEdgeHtmlLabel from 'cytoscape-node-edge-html-label'; @@ -8,6 +8,7 @@ import coseBilkent from 'cytoscape-cose-bilkent'; import expandCollapse from 'cytoscape-expand-collapse'; import fcose from 'cytoscape-fcose'; import Sidebar from '../sidebar/Sidebar'; +import { ZoomContext } from '../zoom-context.provider'; //Make some information available on tooltip hover @@ -86,11 +87,17 @@ const CytoscapeRenderer = ({ }: Props) => { const cyRef = useRef(null); const [cy, setCy] = useState(null); + const { zoomLevel, updateZoom } = useContext(ZoomContext); const [selectedNode, setSelectedNode] = useState(null); const [selectedEdge, setSelectedEdge] = useState(null); useEffect(() => { if (cy) { + //Ensure cytoscape zoom and context state are synchronised + if(cy.zoom() !== zoomLevel) { + updateZoom(cy.zoom()); + } + (cy as any).nodeHtmlLabel([ { query: '.node', @@ -124,6 +131,8 @@ const CytoscapeRenderer = ({ setSelectedEdge(edge?.data()); // Update state with the clicked node's data }); + cy.on('zoom', () => updateZoom(cy.zoom())); + return () => { cy.destroy(); }; @@ -166,11 +175,18 @@ const CytoscapeRenderer = ({ ); }, [nodes, edges]); // Re-render on cy, nodes or edges change + useEffect(() => { + //Ensure cytoscape zoom and context state are synchronised + if(cy?.zoom() !== zoomLevel) { + cy?.zoom(zoomLevel); + } + }, [zoomLevel]) + return (
{title && ( -
- Architecture: {title} +
+ Architecture: {title}
)}
void; @@ -16,6 +18,23 @@ function Navbar({ const upload = (file: File) => { handleUpload(file); }; + const { zoomLevel, updateZoom } = useContext(ZoomContext); + + function zoomIn() { + //Obtain percentage as integer + const currentPercentageZoom = Math.round(zoomLevel*100); + //Add 10% to the zoom or round to upper 10% interval + const newPercentageZoom = Math.floor(currentPercentageZoom/10)*10 + 10; + updateZoom(newPercentageZoom/100); + } + + function zoomOut() { + //Obtain percentage as integer + const currentPercentageZoom = Math.round(zoomLevel*100); + //Subtract 10% from the zoom or round to lower 10% interval - but not less than zero + const newPercentageZoom = Math.max(Math.ceil(currentPercentageZoom/10)*10 - 10, 0); + updateZoom(newPercentageZoom/100); + } return (
@@ -51,8 +70,13 @@ function Navbar({ {isGraphRendered && ( <> -
+
+
+ Zoom: {(zoomLevel*100).toFixed(0)}% + + +