Exemple #1
0
        /**
         * Called whenever anything on the workspace changes.
         * Prevent mismatched types.
         * @param {!Abstract} e Change event.
         * @this Blockly.Block
         */
        protected override void onchange(Events.Abstract e)
        {
            var blockA           = this.getInputTargetBlock("THEN");
            var blockB           = this.getInputTargetBlock("ELSE");
            var parentConnection = this.outputConnection.targetConnection;

            // Disconnect blocks that existed prior to this change if they don't match.
            if ((blockA != null || blockB != null) && parentConnection != null)
            {
                for (var i = 0; i < 2; i++)
                {
                    var block = (i == 1) ? blockA : blockB;
                    if (block != null && !block.outputConnection.checkType_(parentConnection))
                    {
                        // Ensure that any disconnections are grouped with the causing event.
                        Events.setGroup(e.group);
                        if (parentConnection == this.prevParentConnection_)
                        {
                            this.unplug();
                            parentConnection.getSourceBlock().bumpNeighbours_();
                        }
                        else
                        {
                            block.unplug();
                            block.bumpNeighbours_();
                        }
                        Events.setGroup(false);
                    }
                }
            }
            this.prevParentConnection_ = parentConnection;
        }
        /// <summary>
        /// Resize the editor and the underlying block to fit the text.
        /// </summary>
        protected void resizeEditor_(Events.Abstract e = null)
        {
            var div  = WidgetDiv.DIV;
            var bBox = this.fieldGroup_.getBBox();

            div.Style.Width  = bBox.width * this.workspace_.scale + "px";
            div.Style.Height = bBox.height * this.workspace_.scale + "px";
            var xy = this.getAbsoluteXY_();

            // In RTL mode block fields and LTR input fields the left edge moves,
            // whereas the right edge is fixed.  Reposition the editor.
            if (this.sourceBlock_.RTL)
            {
                var borderBBox = this.getScaledBBox_();
                xy.x += borderBBox.width;
                xy.x -= div.OffsetWidth;
            }
            // Shift by a few pixels to line up exactly.
            xy.y += 1;
            if (goog.userAgent.GECKO && WidgetDiv.DIV.Style.Top != null)
            {
                // Firefox mis-reports the location of the border by a pixel
                // once the WidgetDiv is moved into position.
                xy.x -= 1;
                xy.y -= 1;
            }
            if (goog.userAgent.WEBKIT)
            {
                xy.y -= 3;
            }
            div.Style.Left = xy.x + "px";
            div.Style.Top  = xy.y + "px";
        }
Exemple #3
0
 /// <summary>
 /// Enable/disable a block depending on whether it is properly connected.
 /// Use this on applications where all blocks should be connected to a top block.
 /// Recommend setting the 'disable' option to 'false' in the config so that
 /// users don't try to reenable disabled orphan blocks.
 /// </summary>
 /// <param name="ev">Custom data for event.</param>
 public static void disableOrphans(Events.Abstract ev)
 {
     if (ev.type == Events.MOVE ||
         ev.type == Events.CREATE)
     {
         Events.disable();
         var workspace = Workspace.getById(ev.workspaceId);
         var block     = workspace.getBlockById(ev.blockId);
         if (block != null)
         {
             if (block.getParent() != null && !block.getParent().disabled)
             {
                 var children = block.getDescendants();
                 foreach (var child in children)
                 {
                     child.setDisabled(false);
                 }
             }
             else if ((block.outputConnection != null || block.previousConnection != null) &&
                      Core.dragMode_ == Core.DRAG_NONE)
             {
                 do
                 {
                     block.setDisabled(true);
                     block = block.getNextBlock();
                 } while (block != null);
             }
         }
         Events.enable();
     }
 }
Exemple #4
0
        /**
         * Called whenever anything on the workspace changes.
         * Prevent mismatched types from being compared.
         * @param {!Abstract} e Change event.
         * @this Blockly.Block
         */
        protected override void onchange(Events.Abstract e)
        {
            var blockA = this.getInputTargetBlock("A");
            var blockB = this.getInputTargetBlock("B");

            // Disconnect blocks that existed prior to this change if they don't match.
            if (blockA != null && blockB != null &&
                !blockA.outputConnection.checkType_(blockB.outputConnection))
            {
                // Mismatch between two inputs.  Disconnect previous and bump it away.
                // Ensure that any disconnections are grouped with the causing event.
                Events.setGroup(e.group);
                for (var i = 0; i < this.prevBlocks_.Length; i++)
                {
                    var block = this.prevBlocks_[i];
                    if (block == blockA || block == blockB)
                    {
                        block.unplug();
                        block.bumpNeighbours_();
                    }
                }
                Events.setGroup(false);
            }
            this.prevBlocks_[0] = blockA;
            this.prevBlocks_[1] = blockB;
        }
Exemple #5
0
 /// <summary>
 /// Create a custom event and fire it.
 /// </summary>
 /// <param name="ev">Custom data for event.</param>
 public static void fire(Events.Abstract ev)
 {
     if (!Events.isEnabled())
     {
         return;
     }
     if (Events.FIRE_QUEUE_.Length == 0)
     {
         // First event added; schedule a firing of the event queue.
         Window.SetTimeout(Events.fireNow_, 0);
     }
     Events.FIRE_QUEUE_.Push(ev);
 }
Exemple #6
0
        /**
         * Called whenever anything on the workspace changes.
         * Add warning if this flow block is not nested inside a loop.
         * @param {!Abstract} e Change event.
         * @this Blockly.Block
         */
        protected override void onchange(Events.Abstract e)
        {
            if (((WorkspaceSvg)this.workspace).isDragging())
            {
                return;                  // Don't change state at the start of a drag.
            }
            var legal = false;
            // Is the block nested in a procedure?
            var block = (Block)this;

            do
            {
                if (Array.IndexOf(this.FUNCTION_TYPES, block.type) != -1)
                {
                    legal = true;
                    break;
                }
                block = block.getSurroundParent();
            } while (block != null);
            if (legal)
            {
                // If needed, toggle whether this block has a return value.
                if (block.type == ProceduresDefnoreturnBlock.type_name && this.hasReturnValue_)
                {
                    this.removeInput("VALUE");
                    this.appendDummyInput("VALUE")
                    .appendField(Msg.PROCEDURES_DEFRETURN_RETURN);
                    this.hasReturnValue_ = false;
                }
                else if (block.type == ProceduresDefreturnBlock.type_name && !this.hasReturnValue_)
                {
                    this.removeInput("VALUE");
                    this.appendValueInput("VALUE")
                    .appendField(Msg.PROCEDURES_DEFRETURN_RETURN);
                    this.hasReturnValue_ = true;
                }
                this.setWarningText(null);
                if (!this.isInFlyout)
                {
                    this.setDisabled(false);
                }
            }
            else
            {
                this.setWarningText(Msg.PROCEDURES_IFRETURN_WARNING);
                if (!this.isInFlyout && !this.getInheritedDisabled())
                {
                    this.setDisabled(true);
                }
            }
        }
Exemple #7
0
 /// <summary>
 /// Fire a change ev.
 /// </summary>
 /// <param name="ev">Event to fire.</param>
 public void fireChangeListener(Events.Abstract ev)
 {
     if (ev.recordUndo)
     {
         this.undoStack_.Push(ev);
         this.redoStack_.Clear();
         while (this.undoStack_.Length > this.MAX_UNDO)
         {
             this.undoStack_.Shift();
         }
     }
     for (var i = 0; i < this.listeners_.Length; i++)
     {
         this.listeners_[i](ev);
     }
 }
Exemple #8
0
        /**
         * Called whenever anything on the workspace changes.
         * Add warning if this flow block is not nested inside a loop.
         * @param {!Abstract} e Change event.
         * @this Blockly.Block
         */
        protected override void onchange(Events.Abstract e)
        {
            if (((WorkspaceSvg)this.workspace).isDragging())
            {
                return;                  // Don't change state at the start of a drag.
            }
            var legal = false;
            // Is the block nested in a loop?
            var block = (Block)this;

            do
            {
                if (Array.IndexOf(this.LOOP_TYPES, block.type) != -1)
                {
                    legal = true;
                    break;
                }
                block = block.getSurroundParent();
            } while (block != null);
            if (legal)
            {
                this.setWarningText(null);
                if (!this.isInFlyout)
                {
                    this.setDisabled(false);
                }
            }
            else
            {
                this.setWarningText(Msg.CONTROLS_FLOW_STATEMENTS_WARNING);
                if (!this.isInFlyout && !this.getInheritedDisabled())
                {
                    this.setDisabled(true);
                }
            }
        }
Exemple #9
0
        /**
         * Procedure calls cannot exist without the corresponding procedure
         * definition.  Enforce this link whenever an event is fired.
         * @this Blockly.Block
         */
        protected override void onchange(Events.Abstract e)
        {
            if (this.workspace == null || this.workspace.isFlyout)
            {
                // Block is deleted or is in a flyout.
                return;
            }
            if (e.type == Events.CREATE &&
                Array.IndexOf(((Events.Create)e).ids, this.id) != -1)
            {
                // Look for the case where a procedure call was created (usually through
                // paste) and there is no matching definition.  In this case, create
                // an empty definition block with the correct signature.
                var name = this.getProcedureCall();
                var def  = Core.Procedures.getDefinition(name, this.workspace);
                if (def != null && (def.type != this.defType_ ||
                                    JSON.Stringify(def.arguments_.ToArray()) != JSON.Stringify(this.arguments_)))
                {
                    // The signatures don't match.
                    def = null;
                }
                if (def == null)
                {
                    Events.setGroup(e.group);

                    /**
                     * Create matching definition block.
                     * <xml>
                     *   <block type="procedures_defreturn" x="10" y="20">
                     *     <mutation name="test">
                     *       <arg name="x"></arg>
                     *     </mutation>
                     *     <field name="NAME">test</field>
                     *   </block>
                     * </xml>
                     */
                    var xml   = goog.dom.createDom("xml");
                    var block = goog.dom.createDom("block");
                    block.SetAttribute("type", this.defType_);
                    var xy = this.getRelativeToSurfaceXY();
                    var x  = xy.x + Core.SNAP_RADIUS * (this.RTL ? -1 : 1);
                    var y  = xy.y + Core.SNAP_RADIUS * 2;
                    block.SetAttribute("x", x.ToString());
                    block.SetAttribute("y", y.ToString());
                    var mutation = this.mutationToDom();
                    block.AppendChild(mutation);
                    var field = goog.dom.createDom("field");
                    field.SetAttribute("name", "NAME");
                    field.AppendChild(Document.CreateTextNode(this.getProcedureCall()));
                    block.AppendChild(field);
                    xml.AppendChild(block);
                    Xml.domToWorkspace(xml, this.workspace);
                    Events.setGroup(false);
                }
            }
            else if (e.type == Events.DELETE)
            {
                // Look for the case where a procedure definition has been deleted,
                // leaving this block (a procedure call) orphaned.  In this case, delete
                // the orphan.
                var name = this.getProcedureCall();
                var def  = Core.Procedures.getDefinition(name, this.workspace);
                if (def == null)
                {
                    Events.setGroup(e.group);
                    this.dispose(true, false);
                    Events.setGroup(false);
                }
            }
        }