BlockStack MergeStacks(IBlock b1, IBlock b2) { BlockStack ret = new BlockStack(); if ((b1 is BlockStack)) { BlockStack bs1 = b1 as BlockStack; ret.AddRange(bs1); } else { // We need to remove b1 from its parent before adding it to the newly merged stack // otherwise consider such a scenario: // 1- We drag a stack block into an existing stackBlock in a C block // 2- 'b1' is the existing stackBlock, it is not added to ret, but is still an arg of the C block // 3- after merge is called, we'll try to set ret as the arg of the C block; the C will try // to remove the old arg (b1)...but it doesn't have C as a parent! exception thrown b1.ParentRelationship.Detach(this); ret.Add(b1); } if ((b2 is BlockStack)) { BlockStack bs2 = b2 as BlockStack; ret.AddRange(bs2); } else { b2.ParentRelationship.Detach(this); ret.Add(b2); } return(ret); }
public IBlock Split(int nKeep) { if (nKeep < 1 || nKeep >= Blocks.Count) { throw new InvalidOperationException(string.Format("Cannot Split {0} blocks from a {1}-block stack", Blocks.Count - nKeep, Blocks.Count)); } if ((Blocks.Count - nKeep) == 1) { IBlock ret = Blocks.Last(); Detach(ret); Blocks.RemoveAt(nKeep); OnSplit(nKeep); return(ret); } else { BlockStack ret = new BlockStack(); for (int i = nKeep; i < Blocks.Count; ++i) { // Detach(Blocks[i], i); // Not really needed since the new stack will override the attachment ret.Blocks.Add(Blocks[i]); } Blocks.RemoveRange(nKeep, Blocks.Count - nKeep); OnSplit(nKeep); return(ret); } }
internal BlockAttributes AttributeOf(IBlock block) { if (block is InvokationBlock) { InvokationBlock invokation = block as InvokationBlock; return(blockInfos[invokation.Text].Attribute); } else if (block is BlockStack) { BlockStack stack = (BlockStack)block; if (stack.Empty) { return(BlockAttributes.Stack); } if (AttributeOf(stack[0]) == BlockAttributes.Hat) { return(BlockAttributes.Hat); } if (AttributeOf(stack.Last()) == BlockAttributes.Cap) { return(BlockAttributes.Cap); } return(BlockAttributes.Stack); } else if (block is ProcDefBlock) { return(BlockAttributes.Hat); } else if (block is VarAccessBlock) { return(BlockAttributes.Report); } throw new NotImplementedException(); }
private void Run() { // Assume only one block with 'when flag clicked' for now IBlock mainBlock = null; foreach (IBlock b in controller.GetTopLevelBlocks()) { if (b is BlockStack) { BlockStack stack = ((BlockStack)b); IBlock s = stack[0]; if (s is InvokationBlock) { InvokationBlock ib = (InvokationBlock)s; if (ib.Text == "when _flag_ clicked") { mainBlock = b; } } else if (s is ProcDefBlock) { ProcDefBlock pdb = (ProcDefBlock)s; Method m = compiler.DefineMethod(pdb, stack); vm.DefineMethod(pdb.GetMethodString(), m); } } } if (mainBlock != null) { Run(mainBlock); } }
public IBlockView ViewFromBlockStack(BlockStack blocks) { IEnumerable <IBlockView> stack = blocks.Select(b => ViewFromBlock(b)); BlockStackView ret = new BlockStackView(blocks, stack); blocks.OnInsert += new BlockStackInsertEvent(blockstack_OnInsert); return(ret); }
internal IBlock StackBelow(TopLevelScript b1, IBlock b2) { ParentRelationship b2_oldRelationship = b2.ParentRelationship; BlockStack b3 = MergeStacks(b2, b1.Block); RemoveScript(b1); Become(b2_oldRelationship, b2, b3); return(b3); }
public IBlock DeepClone() { BlockStack ret = new BlockStack(); foreach (IBlock block in Blocks) { ret.Add(block); } return(ret); }
public BlockStackView(BlockStack model, IEnumerable <IBlockView> elements) { this.model = model; this.model.OnSplit += new BlockStackSplitEvent(model_OnSplit); this.elements.AddRange(elements); Changed += delegate(object sender) { }; foreach (IBlockView v in this.elements) { Attach(v); } Reassemble(); }
private IBlock ToBlockStack(JToken json) { BlockStack b = new BlockStack(); for (int i = 1; i < json.Count(); ++i) { IBlock subBlock = ToBlock(json[i]); if (i == 1 && subBlock is ProcDefBlock) { currentProcDef = subBlock as ProcDefBlock; } b.Add(subBlock); } currentProcDef = null; return(b); }
BlockStack makeSampleBlockStack() { InvokationBlock b1 = makeInvokationBlock("move % steps", new DataType[] { DataType.Number }, DataType.Script, new IBlock[] { new TextBlock("") }); InvokationBlock b2 = makeInvokationBlock("turn % degrees right", new DataType[] { DataType.Number }, DataType.Script, new IBlock[] { new TextBlock("") }); BlockStack stack = new BlockStack(); stack.AddRange(new IBlock[] { b1, b2 }); return(stack); }
internal void MouseDown(Point p) { if (state == CanvasState.TextEditing) { // Since the mousedown registered, we've clicked outside the textbox ResetTextEditState(); } else if (state == CanvasState.Ready) { if (canvasView.PaletteRect.Contains(p)) { int x = canvasView.PaletteRect.Left; int y = canvasView.PaletteRect.Top; IBlock[] defaultArgs; string funcName = palette.HitTest(p.Offseted(-x, -y), out defaultArgs); if (funcName != "") { IBlock b = blockSpace.makeNewBlock(funcName, defaultArgs); TopLevelScript s = AddTopLevel(b, p.Offseted(-5, -5)); dragged = blockViews[b]; draggingOrigin = p; draggedModel = s; state = CanvasState.Dragging; PrepareDropRegions(b); Update(ViewBounds(dragged)); return; } } IBlockView hit = HitTest(p); if (hit == null) { return; } if (!allViews.ContainsKey(hit)) { if (hit.Model.ParentRelationship.Type == ParentRelationshipType.Stack) { int i = hit.Model.ParentRelationship.Index; Point np = hit.AbsolutePos(); Rectangle bounds = ViewBounds(hit.AbsoluteAncestor()); BlockStack parent = (BlockStack)hit.Model.ParentRelationship.Parent; TopLevelScript splitted = SplitBlockStack(parent, i, np); Update(bounds); draggedModel = splitted; hit = blockViews[splitted.Block]; } else if (hit.Model.ParentRelationship.Type == ParentRelationshipType.Arg) { if (hit is ITextualView) { // We shouldn't detach e.g a number argument from its block // but we should enable the user to edit it SetEditState((ITextualView)hit); return; } int i = hit.Model.ParentRelationship.Index; Point np = hit.AbsolutePos(); Rectangle bounds = ViewBounds(hit.AbsoluteAncestor()); InvokationBlock parent = (InvokationBlock)hit.Model.ParentRelationship.Parent; TopLevelScript splitted = TakeoutBlockArgument(parent, i, np); Update(bounds); draggedModel = splitted; hit = blockViews[splitted.Block]; } else if (hit.Model.ParentRelationship.Type == ParentRelationshipType.FormalParameter) { ProcDefBlock pd = (ProcDefBlock )hit.Model.ParentRelationship.Parent; VarAccessBlock va = new VarAccessBlock((VarDefBlock)pd.Bits[hit.Model.ParentRelationship.Index]); TopLevelScript tls = AddTopLevel(va, p); hit = ViewFromBlock(va); draggedModel = tls; } else if (hit.Model.ParentRelationship.Type == ParentRelationshipType.None) { hit = null; draggedModel = null; } } else { draggedModel = blockSpace.FindScript(hit.Model); } if (hit != null) { dragged = hit; draggingOrigin = p; state = CanvasState.Dragging; PrepareDropRegions(hit.Model); } Update(); } }
public TopLevelScript SplitBlockStack(BlockStack block, int nKeep, Point newStacklocation) { IBlock newStack = block.Split(nKeep); return(AddTopLevel(newStack, newStacklocation)); }
private void testBlockStackView(Point at) { BlockStack stack = makeSampleBlockStack(); controller.AddTopLevel(stack, at); }