/** * @param workspace * @param digits * @requires digits != null * @return List containing a number TextualFactoryBlock and any other blocks containing the * numbers */ public static List<TextualFactoryBlock> getDigits(Workspace workspace, String digits) { Set<TextualFactoryBlock> matchingBlocks = new TreeSet<TextualFactoryBlock>(new MatchingComparator(digits)); // looks through the factory blocks for (RenderableBlock renderable : workspace.getFactoryManager().getBlocks()) { if (renderable == null || renderable.getBlockID().equals(Block.NULL) || !(renderable instanceof FactoryRenderableBlock)) { continue; } // TODO genus name are based from TNG, need to figure out a workaround // selects the number block if (renderable.getBlock().getGenusName().equalsIgnoreCase("number")) { matchingBlocks.add(new TextualFactoryBlock((FactoryRenderableBlock) renderable, digits)); } // selects any other block that contains the number (for variables that contains the number) if (renderable.getKeyword().toLowerCase().contains(digits.toLowerCase())) { matchingBlocks.add( new TextualFactoryBlock( (FactoryRenderableBlock) renderable, renderable.getBlock().getBlockLabel())); } } return new ArrayList<TextualFactoryBlock>(matchingBlocks); }
/** * @param plus * @requires plus != null * @return List containing the two "+" TextualFactoryBlocks and any other blocks containing "+" */ public static List<TextualFactoryBlock> getPlusBlocks(Workspace workspace, String plus) { Set<TextualFactoryBlock> matchingBlocks = new HashSet<TextualFactoryBlock>(); // looks through the factory blocks for (RenderableBlock renderable : workspace.getFactoryManager().getBlocks()) { if (renderable == null || renderable.getBlockID().equals(Block.NULL) || !(renderable instanceof FactoryRenderableBlock)) { continue; } // TODO genus names are based from TNG, need to figure out a workaround // grabs the "+" number and text blocks if (renderable.getBlock().getGenusName().equalsIgnoreCase("sum")) { // changes the label so that the search result will not be ambiguous matchingBlocks.add( new TextualFactoryBlock((FactoryRenderableBlock) renderable, "+ [number]")); } if (renderable.getBlock().getGenusName().equalsIgnoreCase("string-append")) { // changes the label so that the search result will not be ambiguous matchingBlocks.add( new TextualFactoryBlock((FactoryRenderableBlock) renderable, "+ [text]")); } // selects any other block that contains the number (for variables that contains the number) if (renderable.getKeyword().toLowerCase().contains(plus.toLowerCase())) { matchingBlocks.add( new TextualFactoryBlock( (FactoryRenderableBlock) renderable, renderable.getBlock().getBlockLabel())); } } return new ArrayList<TextualFactoryBlock>(matchingBlocks); }
public static void deleteBlock(RenderableBlock block) { block.setLocation(0, 0); WorkspaceWidget widget = block.getParentWidget(); if (widget != null) { widget.removeBlock(block); } Container parent = block.getParent(); if (parent != null) { parent.remove(block); parent.validate(); } block.setParentWidget(null); Workspace workspace = block.getWorkspace(); workspace.notifyListeners( new WorkspaceEvent(workspace, widget, block.getBlockID(), WorkspaceEvent.BLOCK_REMOVED)); }
public static RenderableBlock makeRenderable( Workspace workspace, BlockNode node, WorkspaceWidget widget) { String genusName = node.getGenusName(); // genusName may not be null RenderableBlock renderable = BlockUtilities.getBlock(workspace, genusName, node.getLabel()); if (renderable == null) { throw new RuntimeException("No children block exists for this genus: " + genusName); } Block block = Block.getBlock(renderable.getBlockID()); // assume not null widget.blockDropped(renderable); for (int i = 0; i < node.getChildren().size(); i++) { BlockConnector socket = block.getSocketAt(i); BlockNode child = node.getChildren().get(i); RenderableBlock childRenderable = makeRenderable(workspace, child, widget); Block childBlock = Block.getBlock(childRenderable.getBlockID()); // link blocks BlockLink link; if (childBlock.hasPlug()) { link = BlockLinkChecker.canLink(workspace, block, childBlock, socket, childBlock.getPlug()); } else if (childBlock.hasBeforeConnector()) { link = BlockLinkChecker.canLink( workspace, block, childBlock, socket, childBlock.getBeforeConnector()); } else { link = null; } // assume link is not null link.connect(); workspace.notifyListeners( new WorkspaceEvent( workspace, RenderableBlock.getRenderableBlock(link.getPlugBlockID()).getParentWidget(), link, WorkspaceEvent.BLOCKS_CONNECTED)); } if (node.getAfterNode() != null) { BlockConnector socket = block.getAfterConnector(); // assume has after connector BlockNode child = node.getAfterNode(); RenderableBlock childRenderable = makeRenderable(workspace, child, widget); Block childBlock = Block.getBlock(childRenderable.getBlockID()); // link blocks BlockLink link; if (childBlock.hasPlug()) { link = BlockLinkChecker.canLink(workspace, block, childBlock, socket, childBlock.getPlug()); } else if (childBlock.hasBeforeConnector()) { link = BlockLinkChecker.canLink( workspace, block, childBlock, socket, childBlock.getBeforeConnector()); } else { link = null; } // assume link is not null link.connect(); workspace.notifyListeners( new WorkspaceEvent( workspace, RenderableBlock.getRenderableBlock(link.getPlugBlockID()).getParentWidget(), link, WorkspaceEvent.BLOCKS_CONNECTED)); } 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; }
/** * @param workspace The workspace in use * @param keyword * @requires keyword != null * @return List of TextualFactoryBlocks, {T}, such that: T.toString contains keyword T == null if * no matching blocks were found T.toString is unique for each T */ public static List<TextualFactoryBlock> getAllMatchingBlocks( Workspace workspace, String keyword) { // Use Set such that we don't get any repeats Set<TextualFactoryBlock> matchingBlocks = new TreeSet<TextualFactoryBlock>(new MatchingComparator(keyword)); // find all FactoryRenderableBlocks and check for a match for (RenderableBlock renderable : workspace.getFactoryManager().getBlocks()) { // TODO: don't assume they're all FactoryRenderableBlocks! Collisions aren't... if (renderable == null || renderable.getBlockID().equals(Block.NULL) || !(renderable instanceof FactoryRenderableBlock)) { continue; } // first, check if query matches block keyword if (renderable.getKeyword().toLowerCase().contains(keyword.toLowerCase())) { matchingBlocks.add( new TextualFactoryBlock( (FactoryRenderableBlock) renderable, renderable.getBlock().getBlockLabel())); } // grabs the quote block needed TODO: needs to be independent! if (keyword.startsWith("\"") && renderable.getBlock().getGenusName().equalsIgnoreCase("string")) { String[] quote = keyword.split("\""); // makes sure that there is text after the " so that it can be placed onto the block if (quote.length > 1) { matchingBlocks.add( new TextualFactoryBlock((FactoryRenderableBlock) renderable, "\"" + quote[1] + "\"")); } } // otherwise, if the keyword is too long, check to see if // the user is trying to type extra info for disambiguation else if (keyword.length() > renderable.getKeyword().length()) { if (disambiguousStringRep((FactoryRenderableBlock) renderable) .toLowerCase() .contains(keyword.toLowerCase())) { matchingBlocks.add( new TextualFactoryBlock( (FactoryRenderableBlock) renderable, disambiguousStringRep((FactoryRenderableBlock) renderable))); } } ///////////////////////////////////// // TODO: Add code here for nicknames// ///////////////////////////////////// } /* if blocks have the same labels, the search results will be ambiguous. * the following expands the string representation of the TFB if needed * to disambiguate the blocks. */ ArrayList<TextualFactoryBlock> disambiguatedMatches = new ArrayList<TextualFactoryBlock>(matchingBlocks); TextualFactoryBlock t1, t2; for (int i = 0; i < disambiguatedMatches.size(); i++) { t1 = disambiguatedMatches.get(i); if (i > 0) { t2 = disambiguatedMatches.get(i - 1); if (t1.toString().equals(t2.toString())) { disambiguatedMatches.set( i, new TextualFactoryBlock( t1.getfactoryBlock(), disambiguousStringRep(t1.getfactoryBlock()))); disambiguatedMatches.set( i - 1, new TextualFactoryBlock( t2.getfactoryBlock(), disambiguousStringRep(t2.getfactoryBlock()))); } } if (i < disambiguatedMatches.size() - 1) { t2 = disambiguatedMatches.get(i + 1); if (t1.toString().equals(t2.toString())) { disambiguatedMatches.set( i, new TextualFactoryBlock( t1.getfactoryBlock(), disambiguousStringRep(t1.getfactoryBlock()))); disambiguatedMatches.set( i + 1, new TextualFactoryBlock( t2.getfactoryBlock(), disambiguousStringRep(t2.getfactoryBlock()))); } } } // List<TextualFactoryBlock> f = new ArrayList<TextualFactoryBlock>(); return disambiguatedMatches; }