/// <summary> /// Fetch the type(s) defined in the given input. /// </summary> /// <param name="block"> Block with input.</param> /// <param name="name">Name of the input.</param> /// <returns>List of types.</returns> private static JsArray <string> getTypesFrom_(Blockly.Block block, string name) { var typeBlock = block.getInputTargetBlock(name); JsArray <string> types; if (typeBlock == null || typeBlock.disabled) { types = new JsArray <string>(); } else if (typeBlock.type == "type_other") { types = new JsArray <string> { FactoryUtils.escapeString(typeBlock.getFieldValue("TYPE")) }; } else if (typeBlock.type == "type_group") { types = new JsArray <string>(); for (var n = 0; n < ((TypeGroup)typeBlock).typeCount_; n++) { types = types.Concat(FactoryUtils.getTypesFrom_(typeBlock, "TYPE" + n)); } // Remove duplicates. var hash = new Dictionary <string, object>(); for (var n = types.Length - 1; n >= 0; n--) { if (hash.ContainsKey(types[n])) { types.Splice(n, 1); } hash[types[n]] = true; } } else { var fi = typeBlock.GetType().GetField("valueType", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); types = new JsArray <string> { FactoryUtils.escapeString((string)fi.GetValue(null)) }; } return(types); }
/// <summary> /// Filter the queued events and merge duplicates. /// </summary> /// <param name="queueIn"></param> /// <param name="forward"></param> /// <returns></returns> public static JsArray <Events.Abstract> filter(JsArray <Events.Abstract> queueIn, bool forward) { var queue = new JsArray <Events.Abstract>(queueIn.Clone()); if (!forward) { // Undo is merged in reverse order. queue.Reverse(); } // Merge duplicates. O(n^2), but n should be very small. for (var i = 0; i < queue.Length; i++) { var event1 = queue[i]; for (var j = i + 1; j < queue.Length; j++) { var event2 = queue[j]; if (event1.type == event2.type && event1.blockId == event2.blockId && event1.workspaceId == event2.workspaceId) { if (event1.type == Events.MOVE) { // Merge move events. ((Events.Move)event1).newParentId = ((Events.Move)event2).newParentId; ((Events.Move)event1).newInputName = ((Events.Move)event2).newInputName; ((Events.Move)event1).newCoordinate = ((Events.Move)event2).newCoordinate; queue.Splice(j, 1); j--; } else if (event1.type == Events.CHANGE && ((Events.Change)event1).element == ((Events.Change)event2).element && ((Events.Change)event1).name == ((Events.Change)event2).name) { // Merge change events. ((Events.Change)event1).newValue = ((Events.Change)event2).newValue; queue.Splice(j, 1); j--; } else if (event1.type == Events.UI && ((Events.Ui)event2).element == "click" && (((Events.Ui)event1).element == "commentOpen" || ((Events.Ui)event1).element == "mutatorOpen" || ((Events.Ui)event1).element == "warningOpen")) { // Merge change events. ((Events.Ui)event1).newValue = ((Events.Ui)event2).newValue; queue.Splice(j, 1); j--; } } } } // Remove null events. for (var i = queue.Length - 1; i >= 0; i--) { if (queue[i].isNull()) { queue.Splice(i, 1); } } if (!forward) { // Restore undo order. queue.Reverse(); } // Move mutation events to the top of the queue. // Intentionally skip first event. Events.Abstract ev; for (var i = 1; i < queue.Length; i++) { ev = queue[i]; if (ev.type == Events.CHANGE && ((Events.Change)ev).element == "mutation") { queue.Unshift(queue.Splice(i, 1)[0]); } } return(queue); }