Skip to content

Commit

Permalink
Merge pull request #610 from kbss-cvut/improve-automatic-layout
Browse files Browse the repository at this point in the history
Clicking on apply layout now overrides persisted nodes
  • Loading branch information
blcham authored Sep 30, 2024
2 parents 084f633 + f9b2c23 commit 81508f0
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
28 changes: 28 additions & 0 deletions src/components/editor/faultTree/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,33 @@ const Editor = () => {
}
};

const handleAutomaticLayout = async (graph, jointPaper) => {
for (const el of graph.getElements()) {
const faultEventIri = el.get(JOINTJS_NODE_MODEL.faultEventIri);
const movedEvent = findEventByIri(faultEventIri, getRootEvent());

if (movedEvent) {
const elementView = el.findView(jointPaper);
const size = elementView.model.attributes.size;
const position = elementView.model.attributes.position;
const rect: Rectangle = movedEvent.rectangle;

if (rect.x != position.x || rect.y != position.y || rect.width != size.width || rect.height != size.height) {
rect.x = Math.round(position.x);
rect.y = Math.round(position.y); // The server only supports integers
rect.width = size.width;
rect.height = size.height;

try {
await faultEventService.updateEventRectangle(faultEventIri, rect.iri, rect);
} catch (err) {
console.error("Failed to persist node position", err);
}
}
}
}
};

const highlightBorders = (elementView) => {
const tools = new joint.dia.ToolsView({
tools: [FTABoundary.factory()],
Expand Down Expand Up @@ -219,6 +246,7 @@ const Editor = () => {
onCutSetAnalysis={handleCutSetAnalysis}
onConvertToTable={() => setFailureModesTableOpen(true)}
onNodeMove={handleMoveEvent}
onApplyAutomaticLayout={handleAutomaticLayout}
setHighlightedElement={setHighlightedElementView}
refreshTree={refreshTree}
faultEventScenarios={faultEventScenarios}
Expand Down
32 changes: 16 additions & 16 deletions src/components/editor/faultTree/canvas/EditorCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface Props {
showTable: boolean;
possibleFaultEventScenarios: FaultEventScenario[];
onScenarioSelect: (scenario: FaultEventScenario) => void;
onApplyAutomaticLayout: (container: joint.dia.Graph, jointPaper: joint.dia.Paper) => void;
}

const EditorCanvas = ({
Expand All @@ -71,6 +72,7 @@ const EditorCanvas = ({
showTable,
possibleFaultEventScenarios,
onScenarioSelect,
onApplyAutomaticLayout,
}: Props) => {
const { classes } = useStyles();
const theme = useTheme();
Expand Down Expand Up @@ -210,14 +212,10 @@ const EditorCanvas = ({
}
}, [isExportingImage]);

const addSelf = (shape: any) => {
shape.addTo(container);
layout(container);
};

const layout = (graph) => {
const autoLayoutElements = [];
const manualLayoutElements = [];
const conditionalEventLayoutElements = [];

graph.getElements().forEach((el) => {
const faultEventIri = el.get(JOINTJS_NODE_MODEL.faultEventIri);
if (faultEventIri && faultEventIri === sidebarSelectedEvent?.iri) {
Expand All @@ -226,12 +224,13 @@ const EditorCanvas = ({
}

if (el.get("type") === "fta.ConditioningEvent") {
manualLayoutElements.push(el);
} else if (!el.get(JOINTJS_NODE_MODEL.hasPersistentPosition)) {
conditionalEventLayoutElements.push(el);
} else {
autoLayoutElements.push(el);
}
});
// Automatic Layout

// Apply the automatic layout
joint.layout.DirectedGraph.layout(graph.getSubgraph(autoLayoutElements), {
dagre: dagre,
graphlib: graphlib,
Expand All @@ -241,15 +240,17 @@ const EditorCanvas = ({
rankSep: 100, // Vertical separation between ranks
marginX: 20,
marginY: 20,
preserveNodeGeometry: true,
});
// Manual Layout
manualLayoutElements.forEach((el) => {

// Conditioning Events Manual Layout
conditionalEventLayoutElements.forEach((el) => {
const neighbor = graph.getNeighbors(el, { inbound: true })[0];
if (!neighbor) return;
const neighborPosition = neighbor.getBBox().bottomRight();
el.position(neighborPosition.x + 20, neighborPosition.y - el.size().height / 2 - 20);
});

onApplyAutomaticLayout(graph, jointPaper);
};

const handleDiagramExport = () => {
Expand All @@ -258,7 +259,7 @@ const EditorCanvas = ({
};

useEffect(() => {
const renderAndLayout = async () => {
const render = async () => {
if (container && rootEvent) {
setRendering(true);
container.removeCells(container.getCells());
Expand All @@ -270,12 +271,11 @@ const EditorCanvas = ({
}

await renderTree(container, rootEvent, null, listOfPaths, faultTree?.status);
layout(container);
setRendering(false);
}
};

renderAndLayout();
render();
}, [container, rootEvent, faultEventScenarios]);

useEffect(() => {
Expand Down Expand Up @@ -331,7 +331,7 @@ const EditorCanvas = ({
<SidebarMenuHeader
onExportDiagram={handleDiagramExport}
onConvertToTable={onConvertToTable}
onRestoreLayout={() => layout(container)}
onApplyAutomaticLayout={() => layout(container)}
onCutSetAnalysis={onCutSetAnalysis}
rendering={rendering}
/>
Expand Down
4 changes: 2 additions & 2 deletions src/components/editor/faultTree/menu/SidebarMenuHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const useActionCall = (isModified: boolean, setShowUnsavedChangesDialog: (show:
const SidebarMenuHeader: React.FC<SidebarMenuHeaderProps> = ({
onConvertToTable,
onExportDiagram,
onRestoreLayout,
onApplyAutomaticLayout,
onCutSetAnalysis,
rendering,
}) => {
Expand All @@ -37,7 +37,7 @@ const SidebarMenuHeader: React.FC<SidebarMenuHeaderProps> = ({
<DiagramOptions
onExportDiagram={() => actionCall(onExportDiagram)}
onConvertToTable={() => actionCall(onConvertToTable)}
onRestoreLayout={() => actionCall(onRestoreLayout)}
onApplyAutomaticLayout={() => actionCall(onApplyAutomaticLayout)}
onCutSetAnalysis={() => actionCall(onCutSetAnalysis)}
tableConversionAllowed={!table}
rendering={rendering}
Expand Down
6 changes: 3 additions & 3 deletions src/components/editor/menu/DiagramOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useTranslation } from "react-i18next";
import CircularProgress from "@mui/material/CircularProgress";

export interface Props {
onRestoreLayout: () => void;
onApplyAutomaticLayout: () => void;
onExportDiagram: () => void;
onConvertToTable?: () => void;
onCutSetAnalysis?: () => void;
Expand All @@ -18,7 +18,7 @@ export interface Props {
}

const DiagramOptions = ({
onRestoreLayout,
onApplyAutomaticLayout,
onExportDiagram,
onConvertToTable,
onCutSetAnalysis,
Expand All @@ -33,7 +33,7 @@ const DiagramOptions = ({
Diagram Options
</Typography>
<div>
<IconButton color="primary" onClick={onRestoreLayout} aria-label="restore layout" size="large">
<IconButton color="primary" onClick={onApplyAutomaticLayout} aria-label="restore layout" size="large">
<AccountTreeIcon />
</IconButton>
<IconButton color="primary" onClick={onExportDiagram} aria-label="save" size="large">
Expand Down
2 changes: 1 addition & 1 deletion src/components/editor/system/canvas/EditorCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ const EditorCanvas = ({
))}
</div>
<SidebarMenu className={classes.sidebar}>
<DiagramOptions onRestoreLayout={() => layout(container)} onExportDiagram={handleDiagramExport} />
<DiagramOptions onApplyAutomaticLayout={() => layout(container)} onExportDiagram={handleDiagramExport} />
<Box padding={2} display="flex" alignItems="center">
<Typography noWrap sx={{ flex: 3 }}>
{t("diagramSidePanel.minimumOperationalHours")}
Expand Down

0 comments on commit 81508f0

Please sign in to comment.