diff --git a/src/main/java/edu/mit/blocks/codeblocks/BlockGenus.java b/src/main/java/edu/mit/blocks/codeblocks/BlockGenus.java index ad77269b5a5c23e90b6a2abf236424a5befee54b..04b4d79eae777616e56b11c59a02def94ffc603a 100644 --- a/src/main/java/edu/mit/blocks/codeblocks/BlockGenus.java +++ b/src/main/java/edu/mit/blocks/codeblocks/BlockGenus.java @@ -891,6 +891,13 @@ public class BlockGenus { && newGenus.sockets.get(1).getPositionType() == BlockConnector.PositionType.BOTTOM) { newGenus.isInfix = true; } + //TODO: test -> 3 bottom connectors test - added by letsgoING + else if (newGenus.sockets != null && newGenus.sockets.size() == 3 + && newGenus.sockets.get(0).getPositionType() == BlockConnector.PositionType.BOTTOM + && newGenus.sockets.get(1).getPositionType() == BlockConnector.PositionType.BOTTOM + && newGenus.sockets.get(2).getPositionType() == BlockConnector.PositionType.BOTTOM) { + newGenus.isInfix = true; + } } else if (genusChild.getNodeName().equals("Images")) { /// LOAD BLOCK IMAGES /// loadBlockImages(genusChild.getChildNodes(), newGenus); diff --git a/src/main/java/edu/mit/blocks/codeblocks/InfixBlockShape.java b/src/main/java/edu/mit/blocks/codeblocks/InfixBlockShape.java index a849561a97b37ff5fc1d00212d3e546208499d08..adc4d3cb229ecaa0eea9ab5aff6f652c4f282444 100644 --- a/src/main/java/edu/mit/blocks/codeblocks/InfixBlockShape.java +++ b/src/main/java/edu/mit/blocks/codeblocks/InfixBlockShape.java @@ -43,13 +43,19 @@ public class InfixBlockShape extends BlockShape { //curve down and right BlockShapeUtil.cornerTo(gpBottom, botLeftCorner, botRightCorner, blockCornerRadius); - + //added by letsgoING for new setVariableBlock test + if (block.hasAfterConnector() && !rb.isCollapsed()) { + //control connector if necessary + // Trying left-aligned ports + Point2D p = BCS.addControlConnectorShape(gpBottom, (float) COMMAND_PORT_OFFSET + blockCornerRadius, true); + rb.updateSocketPoint(block.getAfterConnector(), p); + } /// BOTTOM SOCKETS //for each socket in the iterator int socketCounter = 0; //need to use this to determine which socket we're on for (BlockConnector curSocket : block.getSockets()) { - + //if bottom socket if (curSocket.getPositionType() == BlockConnector.PositionType.BOTTOM) { @@ -58,17 +64,18 @@ public class InfixBlockShape extends BlockShape { gpBottom.lineTo( (float) gpBottom.getCurrentPoint().getX() + BOTTOM_SOCKET_MIDDLE_SPACER, (float) gpBottom.getCurrentPoint().getY()); - } else { + }else { gpBottom.lineTo( (float) gpBottom.getCurrentPoint().getX() + BOTTOM_SOCKET_SIDE_SPACER, (float) gpBottom.getCurrentPoint().getY()); } - + //move down so bevel doesn't screw up from connecting infinitely sharp corner // as occurs from a curved port BlockShapeUtil.lineToRelative(gpBottom, 0, -0.1f); + ////////////////////// //begin drawing socket ////////////////////// @@ -86,12 +93,13 @@ public class InfixBlockShape extends BlockShape { (float) gpBottom.getCurrentPoint().getX() + BOTTOM_SOCKET_SIDE_SPACER, (float) gpBottom.getCurrentPoint().getY()); - //draw first socket - down right side BCS.addDataSocket(gpBottom, curSocket.getKind(), false); //rb.updateSocketPoint(curSocket, rightSocket); } else { //there is a connected block Block connectedBlock = rb.getWorkspace().getEnv().getBlock(curSocket.getBlockID()); + + //TODO: check why RBlock on second connector is always NULL??? RenderableBlock connectedRBlock = rb.getWorkspace().getEnv().getRenderableBlock(curSocket.getBlockID()); //calculate and update the new socket point @@ -232,18 +240,27 @@ public class InfixBlockShape extends BlockShape { //System.out.println("determining block width"); int width = super.determineBlockWidth(); - - //if the sum of bottom sockets is greater than the calculated width, then use it + int bottomSocketWidth = 0; + + for (BlockConnector socket : block.getSockets()) { if (socket.getPositionType() == BlockConnector.PositionType.BOTTOM) { if (socket.getBlockID() == Block.NULL) { //3 socket spacers = left of socket, between connectors, right of socket bottomSocketWidth += BOTTOM_SOCKET_SIDE_SPACER; + if(block.isCommandBlock()) {//added by letsgoING for new setVariableBlock test + //TODO get correct size of socket + bottomSocketWidth += rb.accomodateLabelsWidth(); + } } else { //a block is connected to socket //TODO get their assigned width from rb if (rb.getSocketSpaceDimension(socket) != null) { bottomSocketWidth += rb.getSocketSpaceDimension(socket).width; + if(block.isCommandBlock()) {//added by letsgoING for new setVariableBlock test + //TODO get correct size of socket + bottomSocketWidth += rb.accomodateLabelsWidth(); + } } bottomSocketWidth -= BlockConnectorShape.NORMAL_DATA_PLUG_WIDTH; // if it's a mirror plug, subtract for the other side, too. @@ -255,6 +272,7 @@ public class InfixBlockShape extends BlockShape { } + bottomSocketWidth += 2 * BOTTOM_SOCKET_MIDDLE_SPACER; //TODO need to decide for a size of the middle spacer and how to place them bottomSocketWidth += 2 * BOTTOM_SOCKET_SIDE_SPACER; diff --git a/src/main/java/edu/mit/blocks/renderable/NameLabel.java b/src/main/java/edu/mit/blocks/renderable/NameLabel.java index 75ca66dbfd98b5225222330937e7407da569346f..6b4f14b34d85e496273fed921f87ec410ca86afa 100644 --- a/src/main/java/edu/mit/blocks/renderable/NameLabel.java +++ b/src/main/java/edu/mit/blocks/renderable/NameLabel.java @@ -34,11 +34,20 @@ class NameLabel extends BlockLabel { x += 4 + BlockConnectorShape.getConnectorDimensions(rb.getBlock().getPlug()).width; } if (rb.getBlock().isInfix()) { - if (!rb.getBlock().getSocketAt(0).hasBlock()) { - x += 30; - } else { - x += rb.getSocketSpaceDimension(rb.getBlock().getSocketAt(0)).width; - } + //added by letsgoING for new setVariableBlock test + if(rb.getBlock().isCommandBlock()) { + if (!rb.getBlock().getSocketAt(0).hasBlock()) { + x += 60; + } else { + x += rb.getSocketSpaceDimension(rb.getBlock().getSocketAt(0)).width+30; + } + }else { + if (!rb.getBlock().getSocketAt(0).hasBlock()) { + x += 30; + } else { + x += rb.getSocketSpaceDimension(rb.getBlock().getSocketAt(0)).width; + } + } } if (rb.getBlockWidget() == null) { diff --git a/src/main/java/edu/mit/blocks/renderable/RenderableBlock.java b/src/main/java/edu/mit/blocks/renderable/RenderableBlock.java index eb2a7065c57b91f3541a9ff4de8b1541ba507f0e..920869a888092ec74cc5266b41385a84c6c00796 100644 --- a/src/main/java/edu/mit/blocks/renderable/RenderableBlock.java +++ b/src/main/java/edu/mit/blocks/renderable/RenderableBlock.java @@ -147,6 +147,7 @@ public class RenderableBlock extends JComponent implements SearchableElement, * loading as well. In this case, isLoading would still be false */ private boolean isSearchResult = false; + private boolean contextMenueActive = false; private boolean pickedUp = false; private boolean dragging = false; private boolean linkedDefArgsBefore = false; @@ -1597,14 +1598,14 @@ public class RenderableBlock extends JComponent implements SearchableElement, return location; } - public void cloneMe() { - cloneThis(this); + public void cloneMe(boolean cloneFollowing) { + cloneThis(this, cloneFollowing); workspace.notifyListeners(new WorkspaceEvent(workspace, this .getParentWidget(), this.getBlockID(), WorkspaceEvent.BLOCK_CLONED, true)); } - private RenderableBlock cloneThis(RenderableBlock rb) + private RenderableBlock cloneThis(RenderableBlock rb, boolean cloneFollowing) { Block oriBlock = rb.getBlock(); oriBlock.getSockets(); @@ -1626,7 +1627,7 @@ public class RenderableBlock extends JComponent implements SearchableElement, { oriSocket.getBlockID(); RenderableBlock subRb = workspace.getEnv().getRenderableBlock(oriSocket.getBlockID()); - RenderableBlock newSubRb = cloneThis(subRb); + RenderableBlock newSubRb = cloneThis(subRb, true); if (newSubRb.getBlock().isFunctionBlock()) { @@ -1649,7 +1650,7 @@ public class RenderableBlock extends JComponent implements SearchableElement, ++i; } - if (rb.getBlock().isCommandBlock()) + if (rb.getBlock().isCommandBlock() && cloneFollowing) { BlockConnector oriAfterConnector = rb.getBlock().getAfterConnector(); if (oriAfterConnector != null) @@ -1657,7 +1658,7 @@ public class RenderableBlock extends JComponent implements SearchableElement, if (oriAfterConnector.hasBlock()) { RenderableBlock oriAfterRb = workspace.getEnv().getRenderableBlock(oriAfterConnector.getBlockID()); - RenderableBlock newAfterRb = cloneThis(oriAfterRb); + RenderableBlock newAfterRb = cloneThis(oriAfterRb, true); newAfterRb.getBlock().getBeforeConnector().setConnectorBlockID(newRb.getBlockID()); newRb.getBlock().getAfterConnector().setConnectorBlockID(newAfterRb.getBlockID()); @@ -1848,9 +1849,10 @@ public class RenderableBlock extends JComponent implements SearchableElement, public void mouseReleased(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { - if (!pickedUp) { + if (!pickedUp && ! contextMenueActive) { // contextMenueActive -> added by letsgoING throw new RuntimeException("dropping without prior dragging?"); } + contextMenueActive = false; //TODO: check if reset is needed in other places dragHandler.mouseReleased(e); // if the block was dragged before...then @@ -1907,10 +1909,13 @@ public class RenderableBlock extends JComponent implements SearchableElement, } } pickedUp = false; - if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e) || e.isControlDown()) { - if ( SwingUtilities.isRightMouseButton(e) & e.isControlDown()){// added by letsgoING + if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e) || e.isControlDown() || e.isShiftDown()) { + if ( SwingUtilities.isRightMouseButton(e) & e.isControlDown() && e.isShiftDown()){// added by letsgoING //System.out.println("CLONING"); - this.cloneMe(); + this.cloneMe(true); + } + else if(SwingUtilities.isRightMouseButton(e) & e.isControlDown()) { + this.cloneMe(false); } else{ // add context menu at right click location to provide functionality @@ -1918,6 +1923,7 @@ public class RenderableBlock extends JComponent implements SearchableElement, PopupMenu popup = ContextMenu.getContextMenuFor(this); add(popup); popup.show(this, e.getX(), e.getY()); + contextMenueActive = true; //TODO: check where to reset } workspace.getMiniMap().repaint(); } diff --git a/src/main/java/edu/mit/blocks/renderable/SocketLabel.java b/src/main/java/edu/mit/blocks/renderable/SocketLabel.java index 7cc953554868ee0d103750292f14b7e9327bd0ac..b01741678792466af67c970182f5cc9e0e91c2fd 100644 --- a/src/main/java/edu/mit/blocks/renderable/SocketLabel.java +++ b/src/main/java/edu/mit/blocks/renderable/SocketLabel.java @@ -24,7 +24,10 @@ class SocketLabel extends BlockLabel { * @return true if the specified socket should have a corresponding Blocklabel instance added to this. */ static boolean ignoreSocket(BlockConnector socket) { - return (socket.getPositionType() == BlockConnector.PositionType.BOTTOM) || socket.getLabel().equals(""); + //removed bottom-connector from ignore-list for new setVariable-Block by letsgoING + //TODO: TEST for all Blocks -> letsgoING + //return (socket.getPositionType() == BlockConnector.PositionType.BOTTOM) || socket.getLabel().equals(""); + return socket.getLabel().equals(""); } void update(Point2D socketPoint) { diff --git a/src/main/java/edu/mit/blocks/workspace/ContextMenu.java b/src/main/java/edu/mit/blocks/workspace/ContextMenu.java index 14d088c00ddf062e47665ae17d254afec1091bc2..d5208fb0ba344f806377d0760a9618738744f91c 100644 --- a/src/main/java/edu/mit/blocks/workspace/ContextMenu.java +++ b/src/main/java/edu/mit/blocks/workspace/ContextMenu.java @@ -30,8 +30,11 @@ public class ContextMenu extends PopupMenu implements ActionListener { private final static String REMOVE_COMMENT_BLOCK = "REMOVECOMMENT"; private static boolean removeCommentMenuInit = false; private final static String CLONE_BLOCK = "CLONE"; //heqichen + private final static String CLONE_BLOCKS = "CLONEALL"; //letsgoING private static MenuItem cloneItem1 = null; //heqichen private static MenuItem cloneItem2 = null; //heqichen + private static MenuItem cloneAllItem1 = null; //heqichen + private static MenuItem cloneAllItem2 = null; //heqichen //context menu for canvas plus //menu items for canvas context menu private static ContextMenu canvasMenu = new ContextMenu(); @@ -62,6 +65,11 @@ public class ContextMenu extends PopupMenu implements ActionListener { cloneItem1.addActionListener(rndBlockMenu); addCommentMenu.add(cloneItem1); + cloneAllItem1 = new MenuItem(uiMessageBundle.getString("ardublock.ui.clone_all")); + cloneAllItem1.setActionCommand(CLONE_BLOCKS); + cloneAllItem1.addActionListener(rndBlockMenu); + addCommentMenu.add(cloneAllItem1); + addCommentMenuInit = true; } @@ -85,6 +93,11 @@ public class ContextMenu extends PopupMenu implements ActionListener { cloneItem2.addActionListener(rndBlockMenu); removeCommentMenu.add(cloneItem2); + cloneAllItem2 = new MenuItem(uiMessageBundle.getString("ardublock.ui.clone_all")); + cloneAllItem2.setActionCommand(CLONE_BLOCKS); + cloneAllItem2.addActionListener(rndBlockMenu); + removeCommentMenu.add(cloneAllItem2); + removeCommentMenuInit = true; } @@ -152,10 +165,16 @@ public class ContextMenu extends PopupMenu implements ActionListener { if (activeComponent != null && activeComponent instanceof RenderableBlock) { ((RenderableBlock) activeComponent).removeComment(); } - } else if (a.getActionCommand() == CLONE_BLOCK) { + } else if (a.getActionCommand() == CLONE_BLOCKS) { + //notify the renderableblock componenet that lauched the conetxt menu + if (activeComponent != null && activeComponent instanceof RenderableBlock) { + ((RenderableBlock) activeComponent).cloneMe(true); + } + } + else if (a.getActionCommand() == CLONE_BLOCK) { //notify the renderableblock componenet that lauched the conetxt menu if (activeComponent != null && activeComponent instanceof RenderableBlock) { - ((RenderableBlock) activeComponent).cloneMe(); + ((RenderableBlock) activeComponent).cloneMe(false); } } }