com.google.blockly.model.Block

Here are the examples of the java api class com.google.blockly.model.Block taken from open source projects.

1. BlocklyController#bumpBlock()

View license
public void bumpBlock(Connection staticConnection, Connection impingingConnection) {
    Block rootBlock = impingingConnection.getBlock().getRootBlock();
    BlockGroup impingingBlockGroup = mHelper.getRootBlockGroup(rootBlock);
    int maxSnapDistance = mHelper.getMaxSnapDistance();
    int dx = (staticConnection.getPosition().x + maxSnapDistance) - impingingConnection.getPosition().x;
    int dy = (staticConnection.getPosition().y + maxSnapDistance) - impingingConnection.getPosition().y;
    rootBlock.setPosition(rootBlock.getPosition().x + dx, rootBlock.getPosition().y + dy);
    if (mWorkspaceView != null && impingingBlockGroup != null) {
        // Update UI
        impingingBlockGroup.bringToFront();
        impingingBlockGroup.updateAllConnectorLocations();
        mWorkspaceView.requestLayout();
    }
}

2. WorkspaceStatsTest#testCollectProcedureStats()

View license
public void testCollectProcedureStats() {
    Block.Builder blockBuilder = new Block.Builder(ProcedureManager.PROCEDURE_DEFINITION_PREFIX + "test");
    blockBuilder.addInput(mFieldInput);
    Block blockUnderTest = blockBuilder.build();
    mStats.collectStats(blockUnderTest, false);
    verify(mMockProcedureManager).addDefinition(blockUnderTest);
    // Add another block referring to the last one.
    blockBuilder = new Block.Builder(ProcedureManager.PROCEDURE_REFERENCE_PREFIX + "test");
    blockBuilder.addInput(mFieldInput);
    Block procedureReference = blockBuilder.build();
    mStats.collectStats(procedureReference, false);
    verify(mMockProcedureManager).addReference(procedureReference);
}

3. VerticalBlockViewFactoryTest#testBuildBlockViewWithInputs()

View license
// Verify construction of a BlockView for a Block with inputs.
public void testBuildBlockViewWithInputs() {
    final Block block = mBlockFactory.obtainBlock("test_block_one_input_each_type", "TestBlock");
    final BlockView blockView = makeBlockView(block);
    assertNotNull(block);
    assertSame(block, blockView.getBlock());
    // One InputView per Input?
    assertEquals(3, blockView.getInputViewCount());
    for (int inputIdx = 0; inputIdx < 3; ++inputIdx) {
        // Each InputView points to an Input?
        assertNotNull(blockView.getInputView(inputIdx).getInput());
        // Each InputView is a child of the BlockView?
        assertSame(blockView.getInputView(inputIdx), blockView.getChildAt(inputIdx));
        // Each input view points to the correct Input?
        assertSame(block.getInputs().get(inputIdx), blockView.getInputView(inputIdx).getInput());
    }
}

4. BlocklyController#connectAfter()

View license
/**
     * Connects two blocks together in a previous-next relationship and merges the {@link
     * BlockGroup} of the inferior block into the {@link BlockGroup} of the superior block.
     *
     * @param superior The {@link Block} that the inferior block is moving to attach to.
     * @param superiorBlockGroup The {@link BlockGroup} belonging to the superior block.
     * @param inferior The {@link Block} that will follow immediately after the superior block.
     * @param inferiorBlockGroup The {@link BlockGroup} belonging to the inferior block.
     */
private void connectAfter(Block superior, BlockGroup superiorBlockGroup, Block inferior, BlockGroup inferiorBlockGroup) {
    // If there's still a next block at this point it should be a shadow. Double check and
    // remove it. If it's not a shadow something went wrong and connect() will crash.
    Block nextBlock = superior.getNextBlock();
    if (nextBlock != null && nextBlock.isShadow()) {
        removeBlockTree(nextBlock);
    }
    // The superior's next connection and the inferior's previous connections must already be
    // disconnected.
    superior.getNextConnection().connect(inferior.getPreviousConnection());
    if (superiorBlockGroup != null) {
        if (inferiorBlockGroup == null) {
            inferiorBlockGroup = mViewFactory.buildBlockGroupTree(inferior, mWorkspace.getConnectionManager(), mTouchHandler);
        }
        superiorBlockGroup.moveBlocksFrom(inferiorBlockGroup, inferior);
    }
}

5. WorkspaceStatsTest#testCollectVariableStats()

View license
public void testCollectVariableStats() {
    Block.Builder blockBuilder = new Block.Builder("test");
    blockBuilder.addInput(mVariableFieldsInput);
    Block variableReference = blockBuilder.build();
    mStats.collectStats(variableReference, false);
    assertTrue(mStats.getVariableNameManager().contains("variable name"));
    assertFalse(mStats.getVariableNameManager().contains("field name"));
    assertEquals(1, mStats.getVariableReferences().size());
    assertEquals(2, mStats.getVariableReferences().get("variable name").size());
    assertEquals(variableReference.getFieldByName("field name"), mStats.getVariableReferences().get("variable name").get(0));
}

6. ProcedureManagerTest#testAddProcedureDefinitionTwice()

View license
public void testAddProcedureDefinitionTwice() {
    mProcedureManager.addDefinition(mProcedureDefinition);
    try {
        mProcedureManager.addDefinition(mProcedureDefinition);
        fail("Adding the same block twice should be an error");
    } catch (IllegalStateException expected) {
    }
    // Adding two block definitions with the same name should change the name of the new
    // block.
    Block secondProcedureDefinition = (new Block.Builder(mProcedureDefinition)).build();
    mProcedureManager.addDefinition(secondProcedureDefinition);
    assertFalse(PROCEDURE_NAME.equalsIgnoreCase(((FieldInput) secondProcedureDefinition.getFieldByName("name")).getText()));
}

7. BlocklyControllerTest#testExtractAsRootBlock_alreadyRoot()

View license
private void testExtractAsRootBlock_alreadyRoot(boolean withViews) {
    // Configure
    Block block = mBlockFactory.obtainBlock("statement_statement_input", "block");
    mController.addRootBlock(block);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(block);
    }
    // Check Preconditions
    assertEquals(mWorkspace.getRootBlocks().size(), 1);
    assertTrue(mWorkspace.getRootBlocks().contains(block));
    // Run test: Make block a root (even though it already is).
    mController.extractBlockAsRoot(block);
    // Validate (no change)
    assertEquals(mWorkspace.getRootBlocks().size(), 1);
    assertTrue(mWorkspace.getRootBlocks().contains(block));
    if (withViews) {
        BlockGroup firstGroup = mHelper.getParentBlockGroup(block);
        assertSame(firstGroup, mHelper.getRootBlockGroup(block));
    }
}

8. Dragger#finishDragging()

Project: blockly-android
Source File: Dragger.java
View license
/**
     * Finish block dragging. Called during ACTION_DRAG_ENDED and ACTION_DROP.
     * <p/>
     * This method must be called upon receiving the "up" event that ends an ongoing drag process.
     */
@VisibleForTesting
void finishDragging() {
    Block dragRoot = mPendingDrag.getRootDraggedBlock();
    // Maybe snap to connections
    Pair<Connection, Connection> connectionCandidate = findBestConnection(dragRoot);
    if (connectionCandidate != null) {
        mController.connect(dragRoot, connectionCandidate.first, connectionCandidate.second);
    }
    finalizeMove();
}

9. BlocklyControllerTest#testConnect_previousToNextShadowSplice()

View license
private void testConnect_previousToNextShadowSplice(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_no_input", "target");
    Block tail1 = mBlockFactory.obtainBlock("statement_no_input", "tail1");
    Block tail2 = mBlockFactory.obtainBlock("statement_no_input", "tail2");
    Block source = mBlockFactory.obtainBlock("statement_no_input", "source");
    Block shadowTail = new Block.Builder(tail1).setShadow(true).setUuid("shadowTail").build();
    BlockView targetView = null, tailView1 = null, tailView2 = null, sourceView = null;
    // Create a sequence of target, tail1, and tail2.
    tail1.getPreviousConnection().connect(target.getNextConnection());
    tail2.getPreviousConnection().connect(tail1.getNextConnection());
    source.getNextConnection().setShadowConnection(shadowTail.getPreviousConnection());
    source.getNextConnection().connect(shadowTail.getPreviousConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        targetView = mHelper.getView(target);
        tailView1 = mHelper.getView(tail1);
        tailView2 = mHelper.getView(tail2);
        sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(tailView1);
        assertNotNull(tailView2);
        assertNotNull(sourceView);
        assertNotNull(mHelper.getView(shadowTail));
    }
    // Run test: Connect source after target, where tail is currently attached.
    // Since source has a shadow connected to next, tail should replace it.
    mController.connect(source, source.getPreviousConnection(), target.getNextConnection());
    // Target and source are connected.
    assertTrue(mWorkspace.isRootBlock(target));
    assertSame(target, source.getPreviousBlock());
    // Tail has replaced the shadow.
    assertFalse(mWorkspace.isRootBlock(tail1));
    assertNull(shadowTail.getPreviousBlock());
    assertSame(source, tail1.getParentBlock());
    assertFalse(mWorkspace.isRootBlock(tail2));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, tail1.getRootBlock());
    assertSame(target, tail2.getRootBlock());
    if (withViews) {
        BlockGroup targetRootGroup = mHelper.getRootBlockGroup(target);
        assertSame(targetRootGroup, mHelper.getParentBlockGroup(target));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(source));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(tail1));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(tail2));
        assertSame(targetView, targetRootGroup.getChildAt(0));
        assertSame(sourceView, targetRootGroup.getChildAt(1));
        assertSame(tailView1, targetRootGroup.getChildAt(2));
        assertSame(tailView2, targetRootGroup.getChildAt(3));
        assertNull(mHelper.getView(shadowTail));
    }
}

10. BlocklyControllerTest#testConnect_previousToNextSplice()

View license
private void testConnect_previousToNextSplice(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_no_input", "target");
    Block tail = mBlockFactory.obtainBlock("statement_no_input", "tail");
    Block source = mBlockFactory.obtainBlock("statement_no_input", "source");
    Block shadow = new Block.Builder("tail").setShadow(true).setUuid("shadow").build();
    BlockView targetView = null, tailView = null, sourceView = null;
    // Add a shadow to make sure it doesn't have any effects.
    target.getNextConnection().setShadowConnection(shadow.getPreviousConnection());
    tail.getPreviousConnection().connect(target.getNextConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        targetView = mHelper.getView(target);
        tailView = mHelper.getView(tail);
        sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(tailView);
        assertNotNull(sourceView);
    }
    // Connect source after target, where tail is currently attached, causing a splice.
    mController.connect(source, source.getPreviousConnection(), target.getNextConnection());
    assertSame(target, source.getPreviousBlock());
    assertSame(source, tail.getPreviousBlock());
    if (withViews) {
        BlockGroup rootGroup = mHelper.getRootBlockGroup(target);
        assertSame(rootGroup, mHelper.getParentBlockGroup(target));
        assertSame(rootGroup, mHelper.getParentBlockGroup(tail));
        assertSame(rootGroup, mHelper.getParentBlockGroup(source));
        assertSame(targetView, rootGroup.getChildAt(0));
        // Spliced in between.
        assertSame(sourceView, rootGroup.getChildAt(1));
        assertSame(tailView, rootGroup.getChildAt(2));
    }
}

11. BlocklyControllerTest#testConnect_outputToInputSplice()

View license
private void testConnect_outputToInputSplice(boolean withViews) {
    // Setup
    Block target = mBlockFactory.obtainBlock("simple_input_output", "target");
    Block tail = mBlockFactory.obtainBlock("multiple_input_output", "tail");
    Block source = mBlockFactory.obtainBlock("simple_input_output", "source");
    Block shadow = new Block.Builder(tail).setShadow(true).setUuid("shadow").build();
    // Add a hidden shadow to the target to ensure it has no effect.
    target.getOnlyValueInput().getConnection().setShadowConnection(shadow.getOutputConnection());
    // Connect the output of tail to the input of source.
    tail.getOutputConnection().connect(target.getOnlyValueInput().getConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
    }
    // Splice third between second and first.
    mController.connect(source, source.getOutputConnection(), target.getOnlyValueInput().getConnection());
    // Validate
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, source.getOutputConnection().getTargetBlock());
    assertSame(source, tail.getOutputConnection().getTargetBlock());
    if (withViews) {
        BlockGroup targetGroup = mHelper.getParentBlockGroup(target);
        assertSame(targetGroup, mHelper.getRootBlockGroup(target));
        assertSame(targetGroup, mHelper.getRootBlockGroup(tail));
        assertSame(targetGroup, mHelper.getRootBlockGroup(source));
    }
}

12. BlocklyControllerTest#testConnect_outputToInputShadowSplice()

View license
private void testConnect_outputToInputShadowSplice(boolean withViews) {
    // Setup
    Block target = mBlockFactory.obtainBlock("simple_input_output", "target");
    Block tail = mBlockFactory.obtainBlock("simple_input_output", "tail");
    Block source = mBlockFactory.obtainBlock("simple_input_output", "source");
    Block shadow = new Block.Builder(source).setShadow(true).setUuid("shadow").build();
    Connection sourceInputConnection = source.getOnlyValueInput().getConnection();
    // Connect the output of tail to the input of target.
    target.getOnlyValueInput().getConnection().connect(tail.getOutputConnection());
    // Add the shadow to the source
    sourceInputConnection.setShadowConnection(shadow.getOutputConnection());
    sourceInputConnection.connect(shadow.getOutputConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
    }
    // Validate preconditions
    assertEquals(2, mWorkspace.getRootBlocks().size());
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertTrue(mWorkspace.isRootBlock(source));
    // Perform test: Connect the source to where the tail is currently attached.
    mController.connect(source, source.getOutputConnection(), target.getOnlyValueInput().getConnection());
    // source is now a child of target, and tail replaced the shadow
    assertEquals(1, mWorkspace.getRootBlocks().size());
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertSame(target, target.getRootBlock());
    assertSame(target, source.getRootBlock());
    assertSame(target, tail.getRootBlock());
    assertSame(source, tail.getParentBlock());
    if (withViews) {
        BlockGroup targetGroup = mHelper.getParentBlockGroup(target);
        assertSame(targetGroup, mHelper.getRootBlockGroup(target));
        assertSame(targetGroup, mHelper.getRootBlockGroup(source));
        assertSame(targetGroup, mHelper.getRootBlockGroup(tail));
        assertNull(mHelper.getView(shadow));
    }
}

13. BlocklyControllerTest#testConnect_previousToNextBumpRemainder()

View license
private void testConnect_previousToNextBumpRemainder(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_no_input", "target");
    Block tail1 = mBlockFactory.obtainBlock("statement_no_input", "tail1");
    Block tail2 = mBlockFactory.obtainBlock("statement_no_input", "tail2");
    Block source = mBlockFactory.obtainBlock("statement_no_next", "source");
    BlockView targetView = null, tailView1 = null, tailView2 = null, sourceView = null;
    // Create a sequence of target, tail1, and tail2.
    tail1.getPreviousConnection().connect(target.getNextConnection());
    tail2.getPreviousConnection().connect(tail1.getNextConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        targetView = mHelper.getView(target);
        tailView1 = mHelper.getView(tail1);
        tailView2 = mHelper.getView(tail2);
        sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(tailView1);
        assertNotNull(tailView2);
        assertNotNull(sourceView);
    }
    // Run test: Connect source after target, where tail is currently attached.
    // Since source does not have a next connection, bump the tail.
    mController.connect(source, source.getPreviousConnection(), target.getNextConnection());
    // Target and source are connected.
    assertTrue(mWorkspace.isRootBlock(target));
    assertSame(target, source.getPreviousBlock());
    // Tail has been returned to the workspace root.
    assertTrue(mWorkspace.isRootBlock(tail1));
    assertNull(tail1.getPreviousBlock());
    assertFalse(mWorkspace.isRootBlock(tail2));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(tail1, tail1.getRootBlock());
    assertSame(tail1, tail2.getRootBlock());
    if (withViews) {
        BlockGroup targetRootGroup = mHelper.getRootBlockGroup(target);
        BlockGroup tailRootGroup = mHelper.getRootBlockGroup(tail1);
        assertSame(targetRootGroup, mHelper.getParentBlockGroup(target));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(source));
        assertNotSame(targetRootGroup, tailRootGroup);
        assertSame(tailRootGroup, mHelper.getRootBlockGroup(tail2));
        assertSame(targetView, targetRootGroup.getChildAt(0));
        assertSame(sourceView, targetRootGroup.getChildAt(1));
        assertSame(tailView1, tailRootGroup.getChildAt(0));
        assertSame(tailView2, tailRootGroup.getChildAt(1));
        // Check that tail has been bumped far enough away.
        assertTrue(mHelper.getMaxSnapDistance() <= tail1.getPreviousConnection().distanceFrom(target.getNextConnection()));
    }
}

14. BlocklyControllerTest#testConnect_previousToStatementSpliceRemainder()

View license
private void testConnect_previousToStatementSpliceRemainder(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_statement_input", "target");
    Block tail = mBlockFactory.obtainBlock("statement_statement_input", "tail");
    Block source = mBlockFactory.obtainBlock("statement_statement_input", "source");
    Block shadow = new Block.Builder(tail).setShadow(true).setUuid("shadow").build();
    BlockView targetView = null, tailView = null, sourceView = null;
    Connection statementConnection = target.getInputByName("statement input").getConnection();
    // and set a shadow to make sure it has no effects
    statementConnection.setShadowConnection(shadow.getPreviousConnection());
    // Connect the tail inside target.
    statementConnection.connect(tail.getPreviousConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        targetView = mHelper.getView(target);
        tailView = mHelper.getView(tail);
        sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(tailView);
        assertNotNull(sourceView);
    }
    // Run test: Connect source inside target, where tail is attached, resulting in a splice.
    mController.connect(source, source.getPreviousConnection(), statementConnection);
    // Validate result.
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, source.getPreviousBlock());
    assertSame(source, tail.getPreviousBlock());
    if (withViews) {
        BlockGroup rootGroup = mHelper.getRootBlockGroup(target);
        BlockGroup secondGroup = mHelper.getParentBlockGroup(tail);
        assertSame(rootGroup, mHelper.getRootBlockGroup(tail));
        assertNotSame(rootGroup, secondGroup);
        assertSame(secondGroup, mHelper.getParentBlockGroup(source));
        assertSame(sourceView, secondGroup.getChildAt(0));
        assertSame(tailView, secondGroup.getChildAt(1));
    }
}

15. BlocklyControllerTest#testConnect_previousToStatementShadowSplice()

View license
private void testConnect_previousToStatementShadowSplice(boolean withViews) {
    Block target = mBlockFactory.obtainBlock("statement_statement_input", "target");
    Block tail = mBlockFactory.obtainBlock("statement_statement_input", "tail");
    Block source = mBlockFactory.obtainBlock("statement_no_input", "source");
    Block shadow = new Block.Builder(source).setShadow(true).setUuid("shadow").build();
    BlockView sourceView = null;
    // Connect tail inside target.
    Connection statementConnection = target.getInputByName("statement input").getConnection();
    statementConnection.connect(tail.getPreviousConnection());
    // Add the shadow to the source
    source.getNextConnection().setShadowConnection(shadow.getPreviousConnection());
    source.getNextConnection().connect(shadow.getPreviousConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        sourceView = mHelper.getView(source);
        assertNotNull(sourceView);
        assertNotNull(mHelper.getView(shadow));
    }
    // Connect source inside target, where tail is attached.  Source has a shadow on next, so
    // tail should replace it.
    mController.connect(source, source.getPreviousConnection(), statementConnection);
    // Validate
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(statementConnection, source.getPreviousConnection().getTargetConnection());
    assertSame(source, tail.getPreviousBlock());
    assertNull(shadow.getParentBlock());
    if (withViews) {
        BlockGroup targetRootGroup = mHelper.getRootBlockGroup(target);
        BlockGroup sourceGroup = mHelper.getParentBlockGroup(source);
        assertSame(targetRootGroup, mHelper.getParentBlockGroup(target));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(tail));
        assertSame(sourceGroup, mHelper.getParentBlockGroup(tail));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(source));
        assertSame(sourceGroup.getParent(), target.getInputByName("statement input").getView());
        assertSame(sourceView, sourceGroup.getChildAt(0));
        assertSame(mHelper.getView(tail), sourceGroup.getChildAt(1));
        assertNull(mHelper.getView(shadow));
    }
    // Make sure nothing breaks when we detach the tail and the shadow comes back
    mController.extractBlockAsRoot(tail);
}

16. BlocklyControllerTest#testConnect_previousToStatement()

View license
private void testConnect_previousToStatement(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_statement_input", "target");
    Block source = mBlockFactory.obtainBlock("statement_statement_input", "source");
    Block shadow = new Block.Builder(source).setShadow(true).setUuid("shadow").build();
    Connection statementConnection = target.getInputByName("statement input").getConnection();
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
    }
    // Run test: Connect source inside target. No prior connection to bump.
    mController.connect(source, source.getPreviousConnection(), statementConnection);
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, source.getPreviousBlock());
    if (withViews) {
        BlockGroup rootGroup = mHelper.getRootBlockGroup(target);
        assertSame(rootGroup, mHelper.getParentBlockGroup(target));
        assertSame(rootGroup, mHelper.getRootBlockGroup(source));
    }
    // Add the shadow block
    statementConnection.setShadowConnection(shadow.getPreviousConnection());
    // disconnect the real blocks which should attach the shadow to replace it.
    mController.extractBlockAsRoot(source);
    assertTrue(mWorkspace.isRootBlock(source));
    assertFalse(mWorkspace.isRootBlock(shadow));
    assertSame(statementConnection.getTargetBlock(), shadow);
    if (withViews) {
        assertNotNull(mHelper.getView(shadow));
        assertSame(mHelper.getRootBlockGroup(target), mHelper.getRootBlockGroup(shadow));
    }
    // Reconnect the source and make sure the shadow goes away
    mController.connect(source, source.getPreviousConnection(), statementConnection);
    assertNull(shadow.getPreviousBlock());
    assertSame(statementConnection.getTargetBlock(), source);
    assertFalse(mWorkspace.isRootBlock(shadow));
    if (withViews) {
        assertNull(mHelper.getView(shadow));
        assertSame(mHelper.getRootBlockGroup(target), mHelper.getRootBlockGroup(source));
    }
}

17. BlocklyControllerTest#testConnect_previousToStatementBumpRemainder()

View license
private void testConnect_previousToStatementBumpRemainder(boolean withViews) {
    Block target = mBlockFactory.obtainBlock("statement_statement_input", "target");
    Block tail = mBlockFactory.obtainBlock("statement_statement_input", "tail");
    Block source = mBlockFactory.obtainBlock("statement_no_next", "source");
    BlockView sourceView = null;
    // Connect tail inside target.
    target.getInputByName("statement input").getConnection().connect(tail.getPreviousConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        sourceView = mHelper.getView(source);
        assertNotNull(sourceView);
    }
    // Connect source inside target, where tail is attached.  Source does not have a next, so
    // this will bump tail back to the root.
    mController.connect(source, source.getPreviousConnection(), target.getInputByName("statement input").getConnection());
    // Validate
    assertTrue(mWorkspace.isRootBlock(target));
    assertTrue(mWorkspace.isRootBlock(tail));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target.getInputByName("statement input").getConnection(), source.getPreviousConnection().getTargetConnection());
    assertNull(tail.getPreviousBlock());
    if (withViews) {
        BlockGroup targetRootGroup = mHelper.getRootBlockGroup(target);
        BlockGroup tailRootGroup = mHelper.getRootBlockGroup(tail);
        BlockGroup sourceGroup = mHelper.getParentBlockGroup(source);
        assertSame(targetRootGroup, mHelper.getParentBlockGroup(target));
        assertNotSame(targetRootGroup, tailRootGroup);
        assertSame(tailRootGroup, mHelper.getParentBlockGroup(tail));
        assertSame(targetRootGroup, mHelper.getRootBlockGroup(source));
        assertSame(sourceGroup.getParent(), target.getInputByName("statement input").getView());
        assertSame(sourceView, sourceGroup.getChildAt(0));
        assertTrue(mHelper.getMaxSnapDistance() <= source.getPreviousConnection().distanceFrom(tail.getPreviousConnection()));
    }
}

18. WorkspaceStatsTest#testCollectConnectionStatsRecursive()

View license
public void testCollectConnectionStatsRecursive() {
    // Make sure we're only recursing on next and input connections, not output or previous.
    Block.Builder blockBuilder = new Block.Builder("first block");
    blockBuilder.addInput(mVariableFieldsInput);
    blockBuilder.setNext(new Connection(Connection.CONNECTION_TYPE_NEXT, null));
    Block firstBlock = blockBuilder.build();
    blockBuilder = new Block.Builder("second block");
    blockBuilder.addInput(mFieldInput);
    blockBuilder.setPrevious(new Connection(Connection.CONNECTION_TYPE_PREVIOUS, null));
    blockBuilder.setNext(new Connection(Connection.CONNECTION_TYPE_NEXT, null));
    Block secondBlock = blockBuilder.build();
    secondBlock.getPreviousConnection().connect(firstBlock.getNextConnection());
    blockBuilder = new Block.Builder("third block");
    Input in = new Input.InputDummy("name input", Input.ALIGN_LEFT);
    Field field = new FieldVariable("nameid", "third block field name");
    field.setFromString("third block variable name");
    in.add(field);
    blockBuilder.addInput(in);
    blockBuilder.setPrevious(new Connection(Connection.CONNECTION_TYPE_PREVIOUS, null));
    Block thirdBlock = blockBuilder.build();
    thirdBlock.getPreviousConnection().connect(secondBlock.getNextConnection());
    mStats.collectStats(secondBlock, true);
    assertTrue(mStats.getVariableNameManager().contains("third block variable name"));
    assertFalse(mStats.getVariableNameManager().contains("variable name"));
    assertTrue(mConnectionManager.getConnections(Connection.CONNECTION_TYPE_INPUT).isEmpty());
    assertTrue(mConnectionManager.getConnections(Connection.CONNECTION_TYPE_OUTPUT).isEmpty());
    assertEquals(2, mConnectionManager.getConnections(Connection.CONNECTION_TYPE_PREVIOUS).size());
    assertEquals(1, mConnectionManager.getConnections(Connection.CONNECTION_TYPE_NEXT).size());
}

19. WorkspaceHelperTest#testGetNearestParentBlockGroup()

View license
// test getParentBlockGroup
public void testGetNearestParentBlockGroup() throws InterruptedException {
    final List<Block> blocks = new ArrayList<>();
    Block root = mBlockFactory.obtainBlock("statement_no_input", null);
    Block cur = root;
    // Make a chain of statement blocks, all of which will be in the same block group.
    for (int i = 0; i < 3; i++) {
        cur.getNextConnection().connect(mBlockFactory.obtainBlock("statement_no_input", null).getPreviousConnection());
        cur = cur.getNextBlock();
    }
    // Add a block that has inputs at the end of the chain.
    cur.getNextConnection().connect(mBlockFactory.obtainBlock("statement_value_input", null).getPreviousConnection());
    cur = cur.getNextBlock();
    // Connect a block as an input.  It should be in its own block group.
    Block hasOutput = mBlockFactory.obtainBlock("output_no_input", null);
    cur.getInputByName("value").getConnection().connect(hasOutput.getOutputConnection());
    blocks.add(root);
    // Add a completely unconnected block.
    blocks.add(mBlockFactory.obtainBlock("statement_no_input", null));
    TestUtils.createViews(blocks, mViewFactory, mockConnectionManager, mWorkspaceView);
    assertSame(mWorkspaceHelper.getParentBlockGroup(root), mWorkspaceHelper.getParentBlockGroup(cur));
    assertNotSame(mWorkspaceHelper.getParentBlockGroup(blocks.get(0)), mWorkspaceHelper.getParentBlockGroup(blocks.get(1)));
    assertNotSame(mWorkspaceHelper.getParentBlockGroup(root), mWorkspaceHelper.getParentBlockGroup(hasOutput));
}

20. WorkspaceHelperTest#testGetRootBlockGroup()

View license
// test getDraggableBlockGroup
public void testGetRootBlockGroup() throws InterruptedException {
    final List<Block> blocks = new ArrayList<>();
    Block root = mBlockFactory.obtainBlock("statement_statement_input", null);
    Block cur = root;
    // statement input on the block above.
    for (int i = 0; i < 3; i++) {
        cur.getInputByName("statement input").getConnection().connect(mBlockFactory.obtainBlock("statement_statement_input", null).getPreviousConnection());
        cur = cur.getInputByName("statement input").getConnection().getTargetBlock();
    }
    // At the end of the chain, add a block as a "next".  It will still be in the same root
    // block group.
    Block finalBlock = mBlockFactory.obtainBlock("statement_no_input", null);
    cur.getNextConnection().connect(finalBlock.getPreviousConnection());
    blocks.add(root);
    // Add a completely unconnected block.
    blocks.add(mBlockFactory.obtainBlock("empty_block", null));
    TestUtils.createViews(blocks, mViewFactory, mockConnectionManager, mWorkspaceView);
    assertSame(mWorkspaceHelper.getRootBlockGroup(root), mWorkspaceHelper.getRootBlockGroup(cur));
    assertSame(mWorkspaceHelper.getRootBlockGroup(root), mWorkspaceHelper.getRootBlockGroup(finalBlock));
    assertNotSame(Arrays.toString(blocks.toArray()), mWorkspaceHelper.getRootBlockGroup(blocks.get(0)), mWorkspaceHelper.getRootBlockGroup(blocks.get(1)));
}

21. BlocklyControllerTest#testConnect_outputToInputBumpMultipleInputs()

View license
private void testConnect_outputToInputBumpMultipleInputs(boolean withViews) {
    // Setup
    Block target = mBlockFactory.obtainBlock("simple_input_output", "target");
    Block tail = mBlockFactory.obtainBlock("simple_input_output", "tail");
    Block source = mBlockFactory.obtainBlock("multiple_input_output", "source");
    // Connect the output of tail to the input of target.
    tail.getOutputConnection().connect(target.getOnlyValueInput().getConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
    }
    // Perform test: Connect the source to where the tail is currently attached.
    mController.connect(source, source.getOutputConnection(), target.getOnlyValueInput().getConnection());
    // Source is now a child of target
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, source.getOutputConnection().getTargetBlock());
    assertSame(target, source.getRootBlock());
    // Tail has been returned to the workspace root, bumped some distance.
    assertNull(tail.getOutputConnection().getTargetBlock());
    assertTrue(mWorkspace.isRootBlock(tail));
    if (withViews) {
        BlockGroup targetGroup = mHelper.getParentBlockGroup(target);
        BlockGroup tailGroup = mHelper.getParentBlockGroup(tail);
        targetGroup.updateAllConnectorLocations();
        tailGroup.updateAllConnectorLocations();
        assertSame(targetGroup, mHelper.getRootBlockGroup(target));
        assertSame(targetGroup, mHelper.getRootBlockGroup(source));
        assertSame(tailGroup, mHelper.getRootBlockGroup(tail));
        assertNotSame(targetGroup, tailGroup);
        assertTrue(mHelper.getMaxSnapDistance() <= source.getOutputConnection().distanceFrom(tail.getOutputConnection()));
    }
}

22. BlocklyControllerTest#testConnect_outputToInputBumpNoInput()

View license
private void testConnect_outputToInputBumpNoInput(boolean withViews) {
    // Setup
    Block target = mBlockFactory.obtainBlock("simple_input_output", "target");
    Block tail = mBlockFactory.obtainBlock("simple_input_output", "tail");
    Block source = mBlockFactory.obtainBlock("output_no_input", "source");
    // Connect the output of tail to the input of target.
    target.getOnlyValueInput().getConnection().connect(tail.getOutputConnection());
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
    }
    // Validate preconditions
    assertEquals(2, mWorkspace.getRootBlocks().size());
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(tail));
    assertTrue(mWorkspace.isRootBlock(source));
    // Perform test: Connect the source to where the tail is currently attached.
    mController.connect(source, source.getOutputConnection(), target.getOnlyValueInput().getConnection());
    // source is now a child of target, and tail is a new root block
    assertEquals(2, mWorkspace.getRootBlocks().size());
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertTrue(mWorkspace.isRootBlock(tail));
    assertSame(target, target.getRootBlock());
    assertSame(target, source.getRootBlock());
    assertSame(tail, tail.getRootBlock());
    assertNull(tail.getOutputConnection().getTargetBlock());
    if (withViews) {
        BlockGroup targetGroup = mHelper.getParentBlockGroup(target);
        BlockGroup tailGroup = mHelper.getParentBlockGroup(tail);
        assertSame(targetGroup, mHelper.getRootBlockGroup(target));
        assertSame(targetGroup, mHelper.getRootBlockGroup(source));
        assertSame(tailGroup, mHelper.getRootBlockGroup(tail));
        assertNotSame(targetGroup, tailGroup);
        // Check that tail has been bumped far enough away.
        assertTrue(mHelper.getMaxSnapDistance() <= tail.getOutputConnection().distanceFrom(source.getOutputConnection()));
    }
}

23. BlocklyControllerTest#testConnect_outputToInput()

View license
private void testConnect_outputToInput(boolean withViews) {
    // Setup
    Block target = mBlockFactory.obtainBlock("simple_input_output", "connectTarget");
    Block source = mBlockFactory.obtainBlock("simple_input_output", "connectSource");
    Connection targetConnection = target.getOnlyValueInput().getConnection();
    Connection sourceConnection = source.getOutputConnection();
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    Block shadow = new Block.Builder(target).setUuid("connectShadow").setShadow(true).build();
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        // Validate initial view state.
        BlockView targetView = mHelper.getView(target);
        BlockView sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(sourceView);
        assertNotSame(mHelper.getRootBlockGroup(target), mHelper.getRootBlockGroup(source));
    }
    // Perform test: connection source's output to target's input.
    mController.connect(source, sourceConnection, targetConnection);
    // Validate model changes.
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, sourceConnection.getTargetBlock());
    if (withViews) {
        // Validate view changes
        BlockGroup targetGroup = mHelper.getParentBlockGroup(target);
        assertSame(targetGroup, mHelper.getRootBlockGroup(target));
        assertSame(targetGroup, mHelper.getRootBlockGroup(source));
    }
    // Add the shadow connection and disconnect the block
    targetConnection.setShadowConnection(shadow.getOutputConnection());
    mController.extractBlockAsRoot(source);
    assertNull(source.getParentBlock());
    // Validate the block was replaced by the shadow
    assertEquals(targetConnection.getTargetBlock(), shadow);
    if (withViews) {
        // Check that the shadow block now has views
        assertNotNull(mHelper.getView(shadow));
        BlockGroup shadowGroup = mHelper.getParentBlockGroup(target);
        assertSame(shadowGroup, mHelper.getRootBlockGroup(shadow));
    }
    // Reattach the block and verify the shadow is hidden again
    mController.connect(source, sourceConnection, targetConnection);
    assertEquals(targetConnection.getTargetBlock(), source);
    assertNull(shadow.getOutputConnection().getTargetBlock());
    if (withViews) {
        assertNull(mHelper.getView(shadow));
    }
}

24. BlocklyControllerTest#testConnect_previousToNext()

View license
private void testConnect_previousToNext(boolean withViews) {
    // setup
    Block target = mBlockFactory.obtainBlock("statement_no_input", "target");
    Block source = mBlockFactory.obtainBlock("statement_no_input", "source");
    Block shadow = new Block.Builder(target).setUuid("connectShadow").setShadow(true).build();
    BlockView targetView = null, sourceView = null;
    mController.addRootBlock(target);
    mController.addRootBlock(source);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(target, source);
        targetView = mHelper.getView(target);
        sourceView = mHelper.getView(source);
        assertNotNull(targetView);
        assertNotNull(sourceView);
    }
    // Connect source after target. No prior connection to bump or splice.
    mController.connect(source, source.getPreviousConnection(), target.getNextConnection());
    // Validate
    assertTrue(mWorkspace.isRootBlock(target));
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target, source.getPreviousBlock());
    if (withViews) {
        BlockGroup rootGroup = mHelper.getRootBlockGroup(target);
        assertSame(rootGroup, mHelper.getParentBlockGroup(target));
        assertSame(rootGroup, mHelper.getParentBlockGroup(source));
        assertSame(targetView, rootGroup.getChildAt(0));
        assertSame(sourceView, rootGroup.getChildAt(1));
    }
    // Add the shadow to the target's next connection so the view will be created.
    target.getNextConnection().setShadowConnection(shadow.getPreviousConnection());
    mController.extractBlockAsRoot(source);
    assertTrue(mWorkspace.isRootBlock(source));
    assertSame(target.getNextBlock(), shadow);
    if (withViews) {
        BlockGroup rootGroup = mHelper.getRootBlockGroup(target);
        assertSame(rootGroup, mHelper.getParentBlockGroup(shadow));
        assertNotSame(rootGroup, mHelper.getParentBlockGroup(source));
        assertSame(mHelper.getView(shadow), rootGroup.getChildAt(1));
    }
    // Reattach the source and verify the shadow went away.
    mController.connect(source, source.getPreviousConnection(), target.getNextConnection());
    assertFalse(mWorkspace.isRootBlock(source));
    assertSame(target.getNextBlock(), source);
    assertNull(shadow.getPreviousBlock());
    if (withViews) {
        assertNull(mHelper.getView(shadow));
    }
}

25. BlocklyControllerTest#testExtractBlockAsRoot_fromNext()

View license
public void testExtractBlockAsRoot_fromNext(boolean withViews) {
    // Configure
    Block first = mBlockFactory.obtainBlock("statement_statement_input", "first block");
    Block second = mBlockFactory.obtainBlock("statement_statement_input", "second block");
    mController.connect(second, second.getPreviousConnection(), first.getNextConnection());
    mController.addRootBlock(first);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(first, second);
    }
    // Check preconditions
    List<Block> rootBlocks = mWorkspace.getRootBlocks();
    assertEquals(rootBlocks.size(), 1);
    assertEquals(rootBlocks.get(0), first);
    assertEquals(second, first.getNextConnection().getTargetBlock());
    if (withViews) {
        assertSame(mHelper.getParentBlockGroup(first), mHelper.getParentBlockGroup(second));
    }
    // Run test: Extract second out from under first.
    mController.extractBlockAsRoot(second);
    // Validate
    rootBlocks = mWorkspace.getRootBlocks();
    assertEquals(rootBlocks.size(), 2);
    assertTrue(rootBlocks.contains(first));
    assertTrue(rootBlocks.contains(second));
    assertFalse(first.getNextConnection().isConnected());
    assertFalse(second.getPreviousConnection().isConnected());
    if (withViews) {
        BlockGroup firstGroup = mHelper.getParentBlockGroup(first);
        assertNotNull(firstGroup);
        BlockGroup secondGroup = mHelper.getParentBlockGroup(second);
        assertNotNull(secondGroup);
        assertNotSame(secondGroup, firstGroup);
    }
}

26. BlocklyControllerTest#testExtractBlockAsRoot_fromInput()

View license
private void testExtractBlockAsRoot_fromInput(boolean withViews) {
    Block first = mBlockFactory.obtainBlock("simple_input_output", "first block");
    Block second = mBlockFactory.obtainBlock("simple_input_output", "second block");
    mController.connect(second, second.getOutputConnection(), first.getOnlyValueInput().getConnection());
    mController.addRootBlock(first);
    if (withViews) {
        mController.initWorkspaceView(mWorkspaceView);
        fakeOnAttachToWindow(first, second);
    }
    // Check preconditions
    List<Block> rootBlocks = mWorkspace.getRootBlocks();
    assertEquals(rootBlocks.size(), 1);
    assertEquals(rootBlocks.get(0), first);
    // Run test: Extract second out from under first.
    mController.extractBlockAsRoot(second);
    rootBlocks = mWorkspace.getRootBlocks();
    assertEquals(rootBlocks.size(), 2);
    assertTrue(rootBlocks.contains(first));
    assertTrue(rootBlocks.contains(second));
    assertFalse(first.getOnlyValueInput().getConnection().isConnected());
    assertFalse(second.getOutputConnection().isConnected());
    if (withViews) {
        BlockGroup firstGroup = mHelper.getParentBlockGroup(first);
        assertNotNull(firstGroup);
        BlockGroup secondGroup = mHelper.getParentBlockGroup(second);
        assertNotNull(secondGroup);
        assertNotSame(secondGroup, firstGroup);
    }
}

27. BlockViewFactory#unregisterView()

View license
/**
     * Removes the mapping to this view from its block.  This should only be called from
     * {@link BlockView#unlinkModel()}, which is already handled in {@link AbstractBlockView}.
     *
     *  @param blockView The BlockView to disassociate from its Block model.
     */
// TODO(#137): Move to ViewPool class.
protected final void unregisterView(BlockView blockView) {
    Block block = blockView.getBlock();
    mBlockIdToView.remove(block.getId());
}

28. BlockViewFactory#buildBlockViewTree()

View license
/**
     * Called to construct the complete hierarchy of views representing a {@link Block} and its
     * subcomponents, added to {@code parentGroup}.
     *
     * @param block The root block to generate a view for.
     * @param parentGroup T
     * @param connectionManager The {@link ConnectionManager} to update when moving connections.
     * @param touchHandler The {@link BlockTouchHandler} to manage all touches.
     *
     * @return A view for the block and all its descendants.
     */
public final BlockView buildBlockViewTree(Block block, BlockGroup parentGroup, ConnectionManager connectionManager, BlockTouchHandler touchHandler) {
    BlockView blockView = getView(block);
    if (blockView != null) {
        throw new IllegalStateException("BlockView already created.");
    }
    List<Input> inputs = block.getInputs();
    final int inputCount = inputs.size();
    List<InputView> inputViews = new ArrayList<>(inputCount);
    for (int i = 0; i < inputCount; i++) {
        Input input = inputs.get(i);
        List<Field> fields = input.getFields();
        List<FieldView> fieldViews = new ArrayList<>(fields.size());
        for (int j = 0; j < fields.size(); j++) {
            fieldViews.add(buildFieldView(fields.get(j)));
        }
        InputView inputView = buildInputView(input, fieldViews);
        if (input.getType() != Input.TYPE_DUMMY) {
            Block targetBlock = input.getConnection().getTargetBlock();
            if (targetBlock != null) {
                // Blocks connected to inputs live in their own BlockGroups.
                BlockGroup subgroup = buildBlockGroupTree(targetBlock, connectionManager, touchHandler);
                inputView.setConnectedBlockGroup(subgroup);
            }
        }
        inputViews.add(inputView);
    }
    blockView = buildBlockView(block, inputViews, connectionManager, touchHandler);
    // TODO(#137): Move to ViewPool class.
    mBlockIdToView.put(block.getId(), new WeakReference<BlockView>(blockView));
    parentGroup.addView((View) blockView);
    Block next = block.getNextBlock();
    if (next != null) {
        // Next blocks live in the same BlockGroup.
        buildBlockViewTree(next, parentGroup, connectionManager, touchHandler);
    // Recursively calls buildBlockViewTree(..) for the rest of the sequence.
    }
    return blockView;
}

29. WorkspaceHelper#getNearestActiveView()

View license
/**
     * Gets the first block up the hierarchy that can be dragged by the user. If the starting
     * block can be manipulated it will be returned.
     *
     * @param startingView The original view that was touched.
     * @return The nearest parent block that the user can manipulate.
     */
public BlockView getNearestActiveView(BlockView startingView) {
    Block block = startingView.getBlock();
    while (block != null) {
        if (block.isDraggable()) {
            return getView(block);
        }
        block = block.getParentBlock();
    }
    return null;
}

30. InputView#onMeasure()

Project: blockly-android
Source File: InputView.java
View license
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!mHasMeasuredFieldsAndInput) {
        throw new IllegalStateException("InputView.measureFieldsAndInputs()" + " must be called before each call to measure().");
    }
    mHasMeasuredFieldsAndInput = false;
    Block block = mInput.getBlock();
    mBlockTopPadding = mPatchManager.computeBlockTopPadding(block);
    // Width is the width of all fields, plus padding, plus width of child.
    final int width = mFieldLayoutWidth + mPatchManager.mBlockTotalPaddingX + mConnectedGroupWidth;
    // Height is maximum of field height with padding or child height, and at least the minimum
    // height for an empty block.
    final int totalPaddingHeight = mPatchManager.computeBlockTotalPaddingY(mInput.getBlock());
    final int height = Math.max(mPatchManager.mMinBlockHeight, Math.max(mMaxFieldHeight + totalPaddingHeight, mConnectedGroupHeight));
    setMeasuredDimension(width, height);
    // By default, the current row inside this input's block should be as high as this view's
    // measured height.
    mRowHeight = height;
}

31. BlockListView#getWorkspaceBlockGroupForTouch()

Project: blockly-android
Source File: BlockListView.java
View license
/**
     * Calculates the workspace point for a {@link PendingDrag}, such that the
     * {@link MotionEvent#ACTION_DOWN} location remains in the same location on the screen
     * (i.e., under the user's finger), and calls {@link OnDragListBlock#getDraggableBlockGroup}
     * with the location. The workspace point accounts for the {@link WorkspaceView}'s location,
     * pan, and scale.
     *
     * @param pendingDrag The {@link PendingDrag} for the gesture.
     * @return The {@link BlockGroup} return by {@link OnDragListBlock#getDraggableBlockGroup}.
     */
@NonNull
protected BlockGroup getWorkspaceBlockGroupForTouch(PendingDrag pendingDrag) {
    BlockView touchedBlockView = pendingDrag.getTouchedBlockView();
    Block rootBlock = touchedBlockView.getBlock().getRootBlock();
    BlockView rootTouchedBlockView = mHelper.getView(rootBlock);
    BlockGroup rootTouchedGroup = rootTouchedBlockView.getParentBlockGroup();
    // Calculate the offset from rootTouchedGroup to touchedBlockView in view
    // pixels. We are assuming there is no scaling or translations between
    // BlockViews.
    View view = (View) touchedBlockView;
    float offsetX = view.getX() + pendingDrag.getTouchDownViewOffsetX();
    float offsetY = view.getY() + pendingDrag.getTouchDownViewOffsetY();
    ViewGroup parent = (ViewGroup) view.getParent();
    while (parent != rootTouchedGroup) {
        view = parent;
        offsetX += view.getX();
        offsetY += view.getY();
        parent = (ViewGroup) view.getParent();
    }
    // Adjust for RTL, where the block workspace coordinate will be in the top right
    if (mHelper.useRtl()) {
        offsetX = rootTouchedGroup.getWidth() - offsetX;
    }
    // Scale into workspace coordinates.
    int wsOffsetX = mHelper.virtualViewToWorkspaceUnits(offsetX);
    int wsOffsetY = mHelper.virtualViewToWorkspaceUnits(offsetY);
    // Offset the workspace coord by the BlockGroup's touch offset.
    mTempWorkspacePoint.setFrom(pendingDrag.getTouchDownWorkspaceCoordinates());
    mTempWorkspacePoint.offset(-wsOffsetX, -wsOffsetY);
    return mOnDragListBlock.getDraggableBlockGroup(mBlocks.indexOf(rootBlock), rootBlock, mTempWorkspacePoint);
}

32. BlockGroup#moveBlocksFrom()

Project: blockly-android
Source File: BlockGroup.java
View license
/**
     * Move block views into this group from the given group, starting with the given block and
     * continuing through its chain of next blocks.
     *
     * @param from The {@link BlockGroup} to move block views from.
     * @param firstBlock The first {@link Block} to move between groups.
     */
public void moveBlocksFrom(BlockGroup from, Block firstBlock) {
    Block cur = firstBlock;
    while (cur != null) {
        View blockView = (View) mWorkspaceHelper.getView(cur);
        from.removeView(blockView);
        this.addView(blockView);
        cur = cur.getNextBlock();
    }
}

33. BlockGroup#getFirstBlockPosition()

Project: blockly-android
Source File: BlockGroup.java
View license
/**
     * @return The workspace position of the top block in this group, or {@code null} if this group
     * is empty.
     */
public WorkspacePoint getFirstBlockPosition() {
    Block topBlock = getFirstBlock();
    return topBlock == null ? null : topBlock.getPosition();
}

34. BlocklyController#connectAsInput()

View license
/**
     * Connect a block or block group to an input on another block and update views as necessary. If
     * the input was already connected, splice the child block or group in.
     *
     * @param parentConn The {@link Connection} on the superior block to connect to.  Must be an
     *                   input.
     * @param childConn The {@link Connection} on the inferior block.  Must be an output or previous
     *                  connection.
     */
private void connectAsInput(Connection parentConn, Connection childConn) {
    InputView parentInputView = parentConn.getInputView();
    Block child = childConn.getBlock();
    BlockGroup childBlockGroup = mHelper.getParentBlockGroup(child);
    Connection previousTargetConnection = null;
    if (parentConn.isConnected()) {
        previousTargetConnection = parentConn.getTargetConnection();
        // If there was a shadow block here delete it from the hierarchy and forget about it.
        if (previousTargetConnection.getBlock().isShadow()) {
            removeBlockTree(previousTargetConnection.getBlock());
            previousTargetConnection = null;
        } else {
            // Otherwise just disconnect for now
            parentConn.disconnect();
            if (parentInputView != null) {
                parentInputView.setConnectedBlockGroup(null);
            }
        }
    }
    // Connect the new block to its parent.
    parentConn.connect(childConn);
    // Try to reconnect the old block at the end.
    if (previousTargetConnection != null) {
        Block previousTargetBlock = previousTargetConnection.getBlock();
        // Traverse the tree to ensure it doesn't branch. We only reconnect if there's a
        // single place it could be reconnected to. The previousTarget will replace a shadow if
        // one was present.
        Connection lastInputConnection = child.getLastUnconnectedInputConnection();
        if (lastInputConnection == null) {
            // Bump and add back to root.
            BlockGroup previousTargetGroup = mHelper.getParentBlockGroup(previousTargetBlock);
            addRootBlock(previousTargetBlock, previousTargetGroup, false);
            bumpBlock(parentConn, previousTargetConnection);
        } else {
            // Connect the previous part
            connectAsInput(lastInputConnection, previousTargetConnection);
        }
    }
    if (mWorkspaceView != null && parentInputView != null) {
        if (childBlockGroup == null) {
            childBlockGroup = mViewFactory.buildBlockGroupTree(child, mWorkspace.getConnectionManager(), mTouchHandler);
        }
        parentInputView.setConnectedBlockGroup(childBlockGroup);
    }
}

35. AbstractInputViewTest#setUp()

View license
@Override
public void setUp() throws Exception {
    super.setUp();
    // Use the BlockFactory to make sure we have real inputs.
    BlockFactory factory = new BlockFactory(getContext(), new int[] { R.raw.test_blocks });
    Block block = factory.obtainBlock("test_block_one_input_each_type", "fake_id");
    mDummyInput = block.getInputs().get(0);
    assertEquals(Input.TYPE_DUMMY, mDummyInput.getType());
}

36. DraggerTest#testRemoveConnectionsDuringDrag()

Project: blockly-android
Source File: DraggerTest.java
View license
public void testRemoveConnectionsDuringDrag() {
    // Setup
    mTargetBlock = mBlockFactory.obtainBlock("simple_input_output", "first block");
    mTouchedBlock = mDraggedBlock = mBlockFactory.obtainBlock("simple_input_output", "second block");
    Block draggedChild = mBlockFactory.obtainBlock("multiple_input_output", "third block");
    mDraggedBlock.getOnlyValueInput().getConnection().connect(draggedChild.getOutputConnection());
    ArrayList<Connection> draggedConnections = new ArrayList<>();
    mDraggedBlock.getAllConnectionsRecursive(draggedConnections);
    assertEquals(5, draggedConnections.size());
    final ArrayList<Connection> removedConnections = new ArrayList<>();
    final ArrayList<Connection> addedConnections = new ArrayList<>();
    Mockito.doAnswer(new Answer() {

        @Override
        public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
            removedConnections.add((Connection) invocationOnMock.getArguments()[0]);
            return null;
        }
    }).when(mMockConnectionManager).removeConnection(any(Connection.class));
    Mockito.doAnswer(new Answer() {

        @Override
        public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
            addedConnections.add((Connection) invocationOnMock.getArguments()[0]);
            return null;
        }
    }).when(mMockConnectionManager).addConnection(any(Connection.class));
    setupDrag();
    dragTouch();
    assertEquals(0, addedConnections.size());
    assertEquals(0, removedConnections.size());
    dragMove();
    assertEquals(draggedConnections.size(), removedConnections.size());
    assertEquals(0, addedConnections.size());
    for (Connection conn : draggedConnections) {
        assertTrue(removedConnections.contains(conn));
        assertTrue(conn.inDragMode());
    }
    // Complete the drag.
    dragRelease();
    assertEquals(draggedConnections.size(), removedConnections.size());
    assertEquals(draggedConnections.size(), addedConnections.size());
    for (Connection conn : draggedConnections) {
        assertTrue(addedConnections.contains(conn));
        assertFalse(conn.inDragMode());
    }
}

37. BlocklyController#connectAfter()

View license
/**
     * Connect a block after another block in the same block group.  Updates views as necessary.  If
     * the superior block already has a "next" block, splices the inferior block between the
     * superior block and its "next" block.
     * <p/>
     * Assumes that the inferior's previous connection is disconnected. Assumes that inferior's
     * blockGroup doesn't currently live at the root level.
     *
     * @param superior The {@link Block} after which the inferior block is connecting.
     * @param inferior The {@link Block} to be connected as the superior block's "next" block.
     */
private void connectAfter(Block superior, Block inferior) {
    // Get the relevant BlockGroups.  Either may be null if view is not initialized.
    BlockGroup superiorBlockGroup = mHelper.getParentBlockGroup(superior);
    BlockGroup inferiorBlockGroup = mHelper.getParentBlockGroup(inferior);
    Block remainderBlock = superior.getNextBlock();
    BlockGroup remainderGroup = null;
    // To splice between two blocks, just need another call to connectAfter.
    if (remainderBlock != null) {
        if (remainderBlock.isShadow()) {
            // If there was a shadow connected just remove it
            removeBlockTree(remainderBlock);
            remainderBlock = null;
        } else {
            // Disconnect the remainder and save it for later
            remainderGroup = (superiorBlockGroup == null) ? null : superiorBlockGroup.extractBlocksAsNewGroup(remainderBlock);
            superior.getNextConnection().disconnect();
        }
    }
    // Connect the new block to its parent
    connectAfter(superior, superiorBlockGroup, inferior, inferiorBlockGroup);
    // is considered in the workspace during connection checks.
    if (remainderBlock != null) {
        // Try to reconnect the remainder to the end of the new sequence. If the last block
        // has no next bump instead. Shadows will be replaced by the remainder.
        Block lastBlock = inferior.getLastBlockInSequence();
        if (lastBlock.getNextConnection() == null) {
            // Nothing to connect to.  Bump and add to root.
            addRootBlock(remainderBlock, remainderGroup, false);
            bumpBlock(inferior.getPreviousConnection(), remainderBlock.getPreviousConnection());
        } else {
            // Connect the remainder
            connectAfter(lastBlock, superiorBlockGroup, remainderBlock, remainderGroup);
        }
    }
}

38. BlocklyController#connectToStatement()

View license
/**
     * Connect a block to a statement input of another block and update views as necessary.  If the
     * statement input already is connected to another block, splice the inferior block between
     * them.
     *
     * @param parentStatementConnection The {@link Connection} on the superior block to be connected
     * to.  Must be on a statement input.
     * @param toConnect The {@link Block} to connect to the statement input.
     */
private void connectToStatement(Connection parentStatementConnection, Block toConnect) {
    Block remainderBlock = parentStatementConnection.getTargetBlock();
    // If there was already a block connected there.
    if (remainderBlock != null) {
        if (remainderBlock.isShadow()) {
            // If it was a shadow just remove it
            removeBlockTree(remainderBlock);
            remainderBlock = null;
        } else {
            // Disconnect the remainder and we'll reattach it below
            parentStatementConnection.disconnect();
            InputView parentInputView = parentStatementConnection.getInputView();
            if (parentInputView != null) {
                parentInputView.setConnectedBlockGroup(null);
            }
        }
    }
    // Connect the new block to the parent
    connectAsInput(parentStatementConnection, toConnect.getPreviousConnection());
    // is considered in the workspace during connection checks.
    if (remainderBlock != null) {
        // Try to reconnect the remainder to the end of the new sequence. Shadows will be
        // replaced by the remainder.
        Block lastBlock = toConnect.getLastBlockInSequence();
        // If lastBlock doesn't have a next bump instead.
        if (lastBlock.getNextConnection() == null) {
            // Nothing to connect to.  Bump and add to root.
            addRootBlock(remainderBlock, mHelper.getParentBlockGroup(remainderBlock), false);
            bumpBlock(parentStatementConnection, remainderBlock.getPreviousConnection());
        } else {
            // Connect the remainder
            connectAfter(lastBlock, remainderBlock);
        }
    }
}

39. BlocklyController#extractBlockAsRoot()

View license
/**
     * Takes a block, and adds it to the root blocks, disconnecting previous or output connections,
     * if previously connected.  No action if the block was already a root block.
     *
     * @param block {@link Block} to extract as a root block in the workspace.
     */
public void extractBlockAsRoot(Block block) {
    Block rootBlock = block.getRootBlock();
    if (block == rootBlock) {
        return;
    }
    boolean isPartOfWorkspace = mWorkspace.isRootBlock(rootBlock);
    BlockView bv = mHelper.getView(block);
    BlockGroup bg = (bv == null) ? null : (BlockGroup) bv.getParent();
    BlockGroup originalRootBlockGroup = (mWorkspaceView == null) ? null : mHelper.getRootBlockGroup(block);
    // Child block
    if (block.getParentConnection() != null) {
        Connection parentConnection = block.getParentConnection();
        Input in = parentConnection.getInput();
        if (in == null) {
            if (bg != null) {
                // Next block
                bg = bg.extractBlocksAsNewGroup(block);
            }
        } else {
            // Statement or value input
            // Disconnect view.
            InputView inView = in.getView();
            if (inView != null) {
                inView.setConnectedBlockGroup(null);
            }
        }
        parentConnection.disconnect();
        // If this is itself a shadow block the answer is 'no'.
        if (!block.isShadow() && parentConnection != null && parentConnection.getShadowBlock() != null) {
            Block shadowBlock = parentConnection.getShadowBlock();
            // We add the shadow as a root and then connect it so we properly add all the
            // connectors and views.
            addRootBlock(shadowBlock, null, true);
            connect(shadowBlock, parentConnection.getShadowConnection(), parentConnection);
        }
    }
    if (originalRootBlockGroup != null) {
        originalRootBlockGroup.requestLayout();
    }
    if (isPartOfWorkspace) {
        // Only add back to the workspace if the original tree is part of the workspace model.
        addRootBlock(block, bg, false);
    }
}