/** {@inheritDoc} */ @Override public void actionPerformed(ActionEvent e) { final XcosDiagram parentGraph = (XcosDiagram) getGraph(e); // action disabled when the cell is edited final ScilabComponent comp = ((ScilabComponent) parentGraph.getAsComponent()); if (comp.isEditing()) { return; } parentGraph.info(XcosMessages.GENERATE_SUPERBLOCK); parentGraph.getModel().beginUpdate(); try { final SuperBlock superBlock; final Collection<Broken> brokenLinks; final Set<Object> inSelectionCells; /* * Allocate superBlock */ final Object[] selection = parentGraph.getSelectionCells(); final Object[] blocks = XcosDiagram.filterByClass(selection, BasicBlock.class); inSelectionCells = new LinkedHashSet<Object>(Arrays.asList(blocks)); superBlock = allocateSuperBlock(parentGraph, selection); /* * First perform all modification on the parent diagram to handle * well undo/redo operations. */ brokenLinks = updateParent(parentGraph, superBlock, inSelectionCells); /* * Then move some cells to the child diagram */ final SuperBlockDiagram childGraph = moveToChild(parentGraph, superBlock, brokenLinks, inSelectionCells); /* * Finish the install on the child and sync it. */ childGraph.installListeners(); childGraph.installSuperBlockListeners(); superBlock.invalidateRpar(); Xcos.getInstance().addDiagram(parentGraph.getSavedFile(), childGraph); } finally { parentGraph.getModel().endUpdate(); parentGraph.info(XcosMessages.EMPTY_INFO); } }
/** * Allocate a superBlock * * @param parentGraph the base graph * @param selection the selected blocks * @return the allocated super block (without specific listeners) */ private SuperBlock allocateSuperBlock(final XcosDiagram parentGraph, final Object[] selection) { final SuperBlock superBlock = (SuperBlock) BlockFactory.createBlock(INTERFUNCTION_NAME); superBlock.setStyle(INTERFUNCTION_NAME); /* * Allocate the diagram */ final SuperBlockDiagram diag = new SuperBlockDiagram(superBlock); superBlock.setChild(diag); superBlock.setParentDiagram(parentGraph); /* * Place the super block */ final mxRectangle dims = parentGraph.getBoundingBoxFromGeometry(selection); final double minX = dims.getX(); final double maxX = minX + dims.getWidth(); final double minY = dims.getY(); final double maxY = minY + dims.getHeight(); superBlock.getGeometry().setX((maxX + minX - superBlock.getGeometry().getWidth()) / 2.0); superBlock.getGeometry().setY((maxY + minY - superBlock.getGeometry().getHeight()) / 2.0); /* * get statistics */ int angleCounter = 0; int flipCounter = 0; int mirrorCounter = 0; for (Object object : selection) { if (object instanceof BasicBlock) { final BasicBlock b = (BasicBlock) object; angleCounter += b.getAngle(); if (b.getFlip()) { flipCounter++; } if (b.getMirror()) { mirrorCounter++; } } } /* * apply statistics */ final int halfSize = selection.length / 2; superBlock.setAngle(BlockPositioning.roundAngle(angleCounter / selection.length)); superBlock.setFlip(flipCounter > halfSize); superBlock.setMirror(mirrorCounter > halfSize); return superBlock; }
/** * Move the cells to the child graph * * @param parentGraph the parent graph * @param superBlock the superBlock * @param brokenLinks the broken links set * @param inSelectionCells the cells in selection * @return the superblock child diagram */ private SuperBlockDiagram moveToChild( final XcosDiagram parentGraph, final SuperBlock superBlock, final Collection<Broken> brokenLinks, final Set<Object> inSelectionCells) { final SuperBlockDiagram childGraph = superBlock.getChild(); final mxGraphModel childModel = (mxGraphModel) childGraph.getModel(); childModel.beginUpdate(); try { final Collection<Object> cellsToCopy = new ArrayList<Object>(); /* * create a collection with all the cells to move */ cellsToCopy.addAll(inSelectionCells); for (Broken b : brokenLinks) { cellsToCopy.add(b.getChildBlock()); cellsToCopy.add(b.getChildLink()); } /* * Really copy the cells */ final Object[] cells = cellsToCopy.toArray(); parentGraph.removeCells(cells, false); childGraph.addCells(cells); childGraph.setChildrenParentDiagram(); BlockPositioning.updateBlockView(superBlock); } finally { childModel.endUpdate(); } return childGraph; }
/** * Apply compatibility pattern to the decoded object * * @param dec Codec that controls the decoding process. * @param node XML node to decode the object from. * @param obj Object decoded. * @return The Object transformed * @see org.scilab.modules.xcos.io.codec.XcosObjectCodec#afterDecode(com.mxgraph.io.mxCodec, * org.w3c.dom.Node, java.lang.Object) */ @Override public Object afterDecode(mxCodec dec, Node node, Object obj) { if (!(obj instanceof BasicBlock)) { LOG.severe("Unable to decode " + obj); return obj; } final BasicBlock block = (BasicBlock) obj; block.setSimulationFunctionType(SimulationFunctionType.DEFAULT); String functionType = (((Element) node).getAttribute(SIMULATION_FUNCTION_TYPE)); if (functionType != null && functionType.compareTo("") != 0) { SimulationFunctionType type = BasicBlock.SimulationFunctionType.valueOf(functionType); if (type != null) { block.setSimulationFunctionType(type); } } // Re associate the diagram container if (block instanceof SuperBlock) { final SuperBlock superBlock = (SuperBlock) block; if (superBlock.getChild() != null) { superBlock.getChild().setContainer(superBlock); } } // update style to replace direction by rotation and add the // default style if absent StyleMap map = new StyleMap(((Element) node).getAttribute(STYLE)); formatStyle(map, (BasicBlock) obj); block.setStyle(map.toString()); block.updateFieldsFromStyle(); /* * Compat. to remove old specific implementations * * These implementation was available from Scilab-5.2.0 to Scilab-5.3.3. * * Set default values stolen from the old implementation in case of * default value. */ if (node.getNodeName().equals("ConstBlock")) { if (block.getInterfaceFunctionName().equals(BasicBlock.DEFAULT_INTERFACE_FUNCTION)) { block.setInterfaceFunctionName("CONST_m"); } if (block.getSimulationFunctionName().equals(BasicBlock.DEFAULT_SIMULATION_FUNCTION)) { block.setSimulationFunctionName("cstblk4"); } if (block.getValue() == null) { block.setValue("1"); } } if (node.getNodeName().equals("GainBlock")) { if (block.getInterfaceFunctionName().equals(BasicBlock.DEFAULT_INTERFACE_FUNCTION)) { block.setInterfaceFunctionName("GAINBLK_f"); } } // PrintBlock has no default values return super.afterDecode(dec, node, obj); }