public String translate(Long blockId) throws SocketNullException, SubroutineNotDeclaredException { TranslatorBlockFactory translatorBlockFactory = new TranslatorBlockFactory(); Block block = workspace.getEnv().getBlock(blockId); TranslatorBlock rootTranslatorBlock = translatorBlockFactory.buildTranslatorBlock( this, blockId, block.getGenusName(), "", "", block.getBlockLabel()); return rootTranslatorBlock.toCode(); }
public static BlockNode makeNodeWithChildren(Long blockID) { if (isNullBlockInstance(blockID)) { return null; } Block block = Block.getBlock(blockID); String genus = block.getGenusName(); String parentGenus = block instanceof BlockStub ? ((BlockStub) block).getParentGenus() : null; String label; if (!block.labelMustBeUnique() || block instanceof BlockStub) { label = block.getBlockLabel(); } else { label = null; } BlockNode node = new BlockNode(genus, parentGenus, label); for (BlockConnector socket : block.getSockets()) { if (socket.hasBlock()) { node.addChild(makeNodeWithStack(socket.getBlockID())); } } return node; }
public static RenderableBlock cloneBlock(Block myblock) { String mygenusname = myblock.getGenusName(); String label = myblock.getBlockLabel(); final Workspace workspace = myblock.getWorkspace(); // sometimes the factory block will have an assigned label different // from its genus label. if (!myblock.getInitialLabel().equals(myblock.getBlockLabel())) { // acquire prefix and suffix length from myblock label int prefixLength = myblock.getLabelPrefix().length(); int suffixLength = myblock.getLabelSuffix().length(); // we need to set the block label without the prefix and suffix attached because those // values are automatically concatenated to the string specified in setBlockLabel. I know its // weird, but its the way block labels were designed. if (prefixLength > 0 || suffixLength > 0) // TODO we could do this outside of this method, even in constructor { label = myblock .getBlockLabel() .substring(prefixLength, myblock.getBlockLabel().length() - suffixLength); } } // check genus instance counter and if label unique - change label accordingly // also check if label already has a value at the end, if so update counter to have the max // value // TODO ria need to make this smarter // some issues to think about: // - what if they throw out an instance, such as setup2? should the next time they take out // a setup block, should it have setup2 on it? but wouldn't that be confusing? // - when we load up a new project with some instances with numbered labels, how do we keep // track of new instances relative to these old ones? // - the old implementation just iterated through all the instances of a particular genus in the // workspace and compared a possible label to the current labels of that genus. if there // wasn't // any current label that matched the possible label, it returned that label. do we want to // do this? // is there something more efficient? String labelWithIndex = label; // labelWithIndex will have the instance value int value; // initialize value that will be appended to the end of the label if (instanceCounter.containsKey(mygenusname)) { value = instanceCounter.get(mygenusname).intValue(); } else { value = 0; } // begin check for validation of label // iterate until label is valid while (!isLabelValid(myblock, labelWithIndex)) { value++; labelWithIndex = labelWithIndex + value; } // set valid label and save current instance number instanceCounter.put(mygenusname, new Integer(value)); if (!labelWithIndex.equals(label)) // only set it if the label actually changed... { label = labelWithIndex; } Block block; if (myblock instanceof BlockStub) { Block parent = ((BlockStub) myblock).getParent(); block = new BlockStub( workspace, parent.getBlockID(), parent.getGenusName(), parent.getBlockLabel(), myblock.getGenusName()); } else { block = new Block(workspace, myblock.getGenusName(), label); } // TODO - djwendel - create a copy of the RB properties too, using an RB copy constructor. // Don't just use the genus. // RenderableBlock renderable = new RenderableBlock(this.getParentWidget(), block.getBlockID()); RenderableBlock renderable = new RenderableBlock(workspace, null, block.getBlockID()); renderable.setZoomLevel(BlockUtilities.zoom); renderable.redrawFromTop(); renderable.repaint(); return renderable; }
/** * Returns a new RenderableBlock instance with the matching genusName. New block will also have * matching label is label is not-null. May return null. * * @param workspace The workspace to use * @param genusName * @param label * @requires if block associated with genusName has a non editable or unique block label, then * "label" MUST BE NULL. * @return A new RenderableBlock with matching genusName and label (if label is not-null). If no * matching blocks were found, return null. */ public static RenderableBlock getBlock(Workspace workspace, String genusName, String label) { if (genusName == null) { return null; } // find all blocks on the page and look for any match for (Block block : workspace.getBlocks()) { // make sure we're not dealing with null blocks if (block == null || block.getBlockID() == null || block.getBlockID().equals(Block.NULL)) { continue; } // find the block with matching genus and either a matching label or an editable label if (block.getGenusName().equals(genusName) && (block.isLabelEditable() || block.getBlockLabel().equals(label) || block.isInfix())) { // for block stubs, need to make sure that the label matches because stubs of the same kind // (i.e. global var getters, agent var setters, etc.) have the same genusName // but stubs of different parents do not share the same label if (block instanceof BlockStub && !block.getBlockLabel().equals(label)) { continue; } // create new renderable block instance RenderableBlock renderable = BlockUtilities.cloneBlock(block); // make sure renderable block is not a null instance of a block if (renderable == null || renderable.getBlockID().equals(Block.NULL)) { throw new RuntimeException( "Invariant Violated: a valid non null blockID just" + "returned a null instance of RenderableBlock"); // please throw an exception here because it wouldn't make any sense // if the Block is valid but it's associated RenderableBlock is not } // do not drop down default arguments renderable.ignoreDefaultArguments(); // get corresponding block Block newblock = Block.getBlock(renderable.getBlockID()); // make sure corresponding block is not a null instance of block if (newblock == null || newblock.getBlockID().equals(Block.NULL)) { throw new RuntimeException( "Invariant Violated: a valid non null blockID just" + "returned a null instance of Block"); // please throw an exception here because it wouldn't make any sense // if the Block is valid but it's associated RenderableBlock is not } // attempt to set the label text if possible as defined by the specs // should not set the labels of block stubs because their labels are determined by their // parent if ((block.isLabelEditable() || block.getBlockLabel().equals(label))) { if (label != null && !(block instanceof BlockStub)) { if (newblock.isLabelEditable() && !newblock.labelMustBeUnique()) { newblock.setBlockLabel(label); } } } // return renderable block return renderable; } ///////////////////////////////////// // TODO: Add code here for nicknames// ///////////////////////////////////// } // TODO: the part below is a hack. If there are other types of blocks, we need to account for // them return null; }