diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java index e455742..11a6b86 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java @@ -3,7 +3,6 @@ import application.editor.Editor; import application.editor.FlowCellEditor; import application.editor.Stage; -import application.layouts.DAGLayout; import com.mxgraph.model.mxCell; import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxGraphModel; @@ -13,14 +12,12 @@ import com.mxgraph.view.mxGraph; import generators.JavaCodeGenerator; import models.Edge; -import models.Node; import models.algebra.*; -import models.controlFlowModel.*; import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; import models.dataFlowModel.*; +import models.dependencyModel.CheckMxCellLayer; import models.dependencyModel.DependencyGraph; import java.awt.event.MouseAdapter; @@ -82,7 +79,11 @@ resNodeToCell = ((PushPullSelectionStage) prevStage).getResNodeToCell(); eventChannelToCell = ((PushPullSelectionStage) prevStage).getEventChannelToCell(); + + CheckMxCellLayer.printGraphLayers(graph); + clearDependencyGraphCells(graph); graph = constructGraph(graph, dependencyGraph); + CheckMxCellLayer.printGraphLayers(graph); } } @@ -166,23 +167,40 @@ try { Map dependencyResNodeCells = createCellsOfResourceMap(); - Map dependencyEventNodeCells = createEventChannelCells(); + Map dependencyEventNodeCells = createEventChannelCells(); - - graph = insertControlFlowEdges(dependencyResNodeCells, dependencyEventNodeCells); + graph = insertDependencyEdges(dependencyResNodeCells, dependencyEventNodeCells); } finally { graph.getModel().endUpdate(); } return graph; } + private void clearDependencyGraphCells(mxGraph graph) { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dependencyLayer = (mxCell) root.getChildAt(DEPENDENCY_LAYER); + + if (dependencyLayer == null) return; + + graph.getModel().beginUpdate(); + try { + int childCount = dependencyLayer.getChildCount(); + for (int i = childCount - 1; i >= 0; i--) { + dependencyLayer.remove(dependencyLayer.getChildAt(i)); + } + } finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + private Map createCellsOfResourceMap() { Map resNodeCells = new HashMap<>(); mxCell root = (mxCell) graph.getDefaultParent(); mxCell dependencyLayer = (mxCell) root.getChildAt(DEPENDENCY_LAYER); - // トップレベルのリソースノードを探して再帰的にコピー + // Find top-level resource nodes and recursively copy them for (ResourceNode resourceNode : dependencyGraph.getDataFlowGraph().getRootResourceNodes()) { mxCell oldCell = resNodeToCell.get(resourceNode); if (oldCell != null) { @@ -195,7 +213,8 @@ } /** - * 元のセル階層をたどりながら、新しいレイヤー上に同構造のセルツリーを再構築する。 + * Reconstructs an identical cell hierarchy on a new layer + * by traversing the original cell structure. */ private mxCell cloneResourceCellHierarchy(mxCell oldCell, mxCell newParent, Map resNodeCells) { mxGeometry geo = (mxGeometry) oldCell.getGeometry().clone(); @@ -233,8 +252,8 @@ } /** - * セルから対応する ResourceNode を逆引きする補助メソッド。 - * (resNodeToCell の逆引きで探す) + * Helper method to retrieve the corresponding ResourceNode from a cell. + * (Performs reverse lookup from resNodeToCell) */ private ResourceNode findResourceNodeByCell(mxCell cell) { for (Map.Entry entry : resNodeToCell.entrySet()) { @@ -253,13 +272,13 @@ graph.getModel().beginUpdate(); try { - // EventChannel階層を resNodeToCell と同様に再帰的にコピー + // Recursively copy the EventChannel hierarchy for (ChannelNode channelNode : dependencyGraph.getDataFlowGraph().getRootChannelNodes()) { DataTransferChannel channel = channelNode.getChannel(); if (channel.getInputResources().isEmpty()) { mxCell oldCell = eventChannelToCell.get(channel); - if (oldCell != null) { - mxCell newCell = cloneEventChannelHierarchy(oldCell, dependencyLayer, eventChannelCells); + if (oldCell != null && !eventChannelCells.containsKey(channel)) { + mxCell newCell = cloneEventChannelHierarchy(oldCell, dependencyLayer, eventChannelCells, channel); eventChannelCells.put(channel, newCell); } } @@ -271,7 +290,9 @@ return eventChannelCells; } - private mxCell cloneEventChannelHierarchy(mxCell oldCell, mxCell newParent, Map eventChannelCells) { + private mxCell cloneEventChannelHierarchy(mxCell oldCell, mxCell newParent, + Map eventChannelCells, DataTransferChannel rootChannel) { + mxGeometry geo = (mxGeometry) oldCell.getGeometry(); if (geo != null) geo = (mxGeometry) geo.clone(); @@ -286,11 +307,10 @@ double w = (geo != null) ? geo.getWidth() : 40; double h = (geo != null) ? geo.getHeight() : 30; - // 親が dependencyLayer なら channelCell、そうでなければ portなど if (isPortCell(oldCell)) { - // --- ✅ ポート(portOutなど)の場合 --- + // port mxGeometry geoPort = (geo != null) ? geo : new mxGeometry(1.0, 0.5, 10, 10); - geoPort.setRelative(true); // relativeを明示的に指定 + geoPort.setRelative(true); if (geoPort.getOffset() == null) { geoPort.setOffset(new mxPoint(-5, -5)); } @@ -299,41 +319,30 @@ newCell = new mxCell(null, geoPort, portStyle); newCell.setVertex(true); graph.addCell(newCell, newParent); - } else { - // --- 通常のchannelノード --- + // EventChannel String newStyle = "strokeColor=green;fillColor=#BBFFBB;verticalAlign=top"; - newCell = (mxCell) graph.insertVertex( - newParent, - null, - label, - x, y, w, h, - newStyle - ); + newCell = (mxCell) graph.insertVertex(newParent, null, label, x, y, w, h, newStyle); } } else { newCell = new mxCell(label, geo, style); } - // --- channelとの対応を登録 --- - DataTransferChannel channel = findEventChannelByCell(oldCell); - if (channel != null) { - eventChannelCells.put(channel, newCell); + // Associate the channel cell (only if it's a root channel) + if (oldCell == eventChannelToCell.get(rootChannel)) { + eventChannelCells.put(rootChannel, newCell); } - // --- 子セルを再帰的に処理 --- + // Recursively process all child cells int childCount = oldCell.getChildCount(); for (int i = 0; i < childCount; i++) { mxCell oldChild = (mxCell) oldCell.getChildAt(i); - cloneEventChannelHierarchy(oldChild, newCell, eventChannelCells); + cloneEventChannelHierarchy(oldChild, newCell, eventChannelCells, rootChannel); } return newCell; } - /** - * ポートかどうかを判定 - */ private boolean isPortCell(mxCell cell) { String style = cell.getStyle(); if (style == null) return false; @@ -341,18 +350,7 @@ } - private DataTransferChannel findEventChannelByCell(mxCell cell) { - for (Map.Entry entry : eventChannelToCell.entrySet()) { - if (entry.getValue() == cell) { - return entry.getKey(); - } - } - return null; - } - - - - private mxGraph insertControlFlowEdges(final Map resNodeCells, final Map eventChNodeCells) { + private mxGraph insertDependencyEdges(final Map resNodeCells, final Map eventChNodeCells) { mxCell root = (mxCell) graph.getDefaultParent(); mxCell dependencyLayerCell = (mxCell) root.getChildAt(DEPENDENCY_LAYER); diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java index 99b523c..ae4c57f 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java @@ -36,7 +36,7 @@ pullFlowCheckBox = new JCheckBox("Pull-Flow", true); dependencyCheckBox = new JCheckBox("Dependency", false); - // Add handlers to the check boxes. + // Add handlers to the checkboxes. dataFlowCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -86,18 +86,15 @@ @Override public void stageChanged(Stage newStage) { if (newStage instanceof DependencyModelingStage) { - // DependencyStageでは全て操作可能 - dataFlowCheckBox.setEnabled(true); - pushFlowCheckBox.setEnabled(true); - pullFlowCheckBox.setEnabled(true); - dependencyCheckBox.setEnabled(true); + setAllCheckBoxesEnabled(true); - // Dependencyチェックを自動でON + dataFlowCheckBox.setSelected(false); + pushFlowCheckBox.setSelected(false); + pullFlowCheckBox.setSelected(false); dependencyCheckBox.setSelected(true); newStage.setLayerEnabled(Stage.DEPENDENCY_LAYER, true); } else if (newStage instanceof PushPullSelectionStage) { - // PushPullStage:Data,Push,Pullを表示(操作不可) setAllCheckBoxesEnabled(false); dataFlowCheckBox.setSelected(true); pushFlowCheckBox.setSelected(true); @@ -110,7 +107,6 @@ newStage.setLayerEnabled(Stage.DEPENDENCY_LAYER, false); } else if (newStage instanceof DataFlowModelingStage) { - // DataFlowStage:Dataのみ表示(操作不可) setAllCheckBoxesEnabled(false); dataFlowCheckBox.setSelected(true); pushFlowCheckBox.setSelected(false); @@ -122,7 +118,6 @@ newStage.setLayerEnabled(Stage.PULL_FLOW_LAYER, false); newStage.setLayerEnabled(Stage.DEPENDENCY_LAYER, false); } else { - // その他ステージではすべて非活性 setAllCheckBoxesEnabled(false); dataFlowCheckBox.setSelected(false); pushFlowCheckBox.setSelected(false); diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java index f8e1275..22e8eb4 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java @@ -60,19 +60,31 @@ setResizable(false); } - @Override public void stageChanged(Stage newStage) { if (forbidReentry) { return; } + if (newStage instanceof DataFlowModelingStage) { dataFlowModelingButton.setSelected(true); + // DataFlow → PushPullのみ有効 + dataFlowModelingButton.setEnabled(true); pushPullSelectionButton.setEnabled(editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)); + dependencyModelingButton.setEnabled(false); + } else if (newStage instanceof PushPullSelectionStage) { pushPullSelectionButton.setSelected(true); - dependencyModelingButton.setEnabled(editor.canChange(Editor.STAGE_DEPENDENCY_MODELING)); + // PushPull → 全部有効 + dataFlowModelingButton.setEnabled(true); + pushPullSelectionButton.setEnabled(true); + dependencyModelingButton.setEnabled(true); + } else if (newStage instanceof DependencyModelingStage) { dependencyModelingButton.setSelected(true); + // Dependency → 全部有効 + dataFlowModelingButton.setEnabled(true); + pushPullSelectionButton.setEnabled(true); + dependencyModelingButton.setEnabled(true); } } @@ -82,7 +94,10 @@ forbidReentry = true; editor.changeStage(Editor.STAGE_DATA_FLOW_MODELING); forbidReentry = false; + // DataFlow → PushPullのみ有効 + dataFlowModelingButton.setEnabled(true); pushPullSelectionButton.setEnabled(editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)); + dependencyModelingButton.setEnabled(false); } } @@ -92,7 +107,10 @@ forbidReentry = true; editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); forbidReentry = false; - dependencyModelingButton.setEnabled(editor.canChange(Editor.STAGE_DEPENDENCY_MODELING)); + // PushPull → 全部有効 + dataFlowModelingButton.setEnabled(true); + pushPullSelectionButton.setEnabled(true); + dependencyModelingButton.setEnabled(true); } } @@ -102,6 +120,10 @@ forbidReentry = true; editor.changeStage(Editor.STAGE_DEPENDENCY_MODELING); forbidReentry = false; + // Dependency → 全部有効 + dataFlowModelingButton.setEnabled(true); + pushPullSelectionButton.setEnabled(true); + dependencyModelingButton.setEnabled(true); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/CheckMxCellLayer.java b/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/CheckMxCellLayer.java new file mode 100644 index 0000000..da9429d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/CheckMxCellLayer.java @@ -0,0 +1,32 @@ +package models.dependencyModel; + +import application.editor.Stage; +import com.mxgraph.model.mxCell; +import com.mxgraph.view.mxGraph; + +public class CheckMxCellLayer { + + public static void printGraphLayers(mxGraph graph) { + Object root = graph.getDefaultParent(); + System.out.println("=== Graph Structure ==="); + printCellRecursive((mxCell) root, 0); + + System.out.println(((mxCell) root).getChildAt(Stage.DATA_FLOW_LAYER)); + System.out.println(((mxCell) root).getChildAt(Stage.PUSH_FLOW_LAYER)); + System.out.println(((mxCell) root).getChildAt(Stage.PULL_FLOW_LAYER)); + } + + private static void printCellRecursive(mxCell cell, int depth) { + if (cell == null) return; + + String indent = " ".repeat(depth * 2); + System.out.println(indent + "- " + (cell.isVertex() ? "[V]" : cell.isEdge() ? "[E]" : "[C]") + + " name=" + cell.getValue() + + " id=" + cell.getId() + + " visible=" + cell.isVisible()); + + for (int i = 0; i < cell.getChildCount(); i++) { + printCellRecursive((mxCell) cell.getChildAt(i), depth + 1); + } + } +}