/// <summary> /// Delete a variable by the passed in name and all of its uses from this /// workspace.May prompt the user for confirmation. /// </summary> /// <param name="name"> Name of variable to delete.</param> public void DeleteVariable(string name) { // Check wether this variable is a function parameter before deleting. var uses = this.GetVariableUses(name); foreach (var block in uses) { if (string.Equals(block.Type, Define.DEFINE_NO_RETURN_BLOCK_TYPE) || string.Equals(block.Type, Define.DEFINE_WITH_RETURN_BLOCK_TYPE)) { var procedureName = block.GetFieldValue("NAME"); Debug.LogError("Alert:" + I18n.Get(MsgDefine.CANNOT_DELETE_VARIABLE_PROCEDURE). Replace("%1", name). Replace("%2", procedureName)); return; } } var workspace = this; var variable = workspace.GetVariable(name); if (uses.Count > 1) { // Confirm before deleting multiple blocks. Debug.Log("confirm:" + I18n.Get(MsgDefine.DELETE_VARIABLE_CONFIRMATION) .Replace("%1", uses.Count.ToString()).Replace("%2", name)); workspace.DeleteVariableInternal(variable); } else { // No confirmation necessary for a single block. this.DeleteVariableInternal(variable); } }
/// <summary> /// A new set of Inputs reflecting the current Procedure state. /// </summary> protected override List <Input> BuildUpdatedInputs() { List <string> args = mProcedure.Arguments; int argCount = args.Count; List <Input> inputs = new List <Input>(); // Procedure name inputs.Add(mBlock.InputList[0]); // Argument inputs for (int i = 0; i < argCount; ++i) { Input stackInput = InputFactory.Create(Define.EConnection.InputValue, "ARG" + i, Define.EAlign.Right, null); // add "with: " label if (i == 0) { FieldLabel withLabel = new FieldLabel("WITH", I18n.Get(MsgDefine.PROCEDURES_CALL_BEFORE_PARAMS)); stackInput.AppendField(withLabel); } // add argument's label FieldLabel label = new FieldLabel(null, args[i]); stackInput.AppendField(label); inputs.Add(stackInput); } return(inputs); }
/// <summary> /// maoling: private method, please call GetOptions() in FieldDropdown instead!!! /// Return a sorted list of variable names for variable dropdown menus. /// Include a special option at the end for creating a new variable name. /// </summary> private FieldDropdownMenu[] DropdownCreate() { List <VariableModel> varModels = null; string name = GetText(); // Don't create a new variable if there is nothing selected. var createSelectedVariable = !string.IsNullOrEmpty(name); Workspace workspace = SourceBlock != null ? SourceBlock.Workspace : null; if (workspace != null) { // Get a copy of the list, so that adding rename and new variable options // doesn't modify the workspace's list. varModels = workspace.GetVariablesOfType(""); varModels.Sort(VariableModel.CompareByName); } if (varModels == null) { varModels = new List <VariableModel>(); } List <FieldDropdownMenu> options = new List <FieldDropdownMenu>(); for (int i = 0; i < varModels.Count; i++) { options.Add(new FieldDropdownMenu() { Text = varModels[i].Name, Value = varModels[i].ID }); } if (Define.FIELD_VARIABLE_ADD_MANIPULATION_OPTIONS) { options.Add(new FieldDropdownMenu() { Text = I18n.Get(MsgDefine.RENAME_VARIABLE), Value = MsgDefine.RENAME_VARIABLE }); options.Add(new FieldDropdownMenu() { Text = I18n.Get(MsgDefine.DELETE_VARIABLE), Value = MsgDefine.DELETE_VARIABLE }); } return(options.ToArray()); }
/// <summary> /// A human-readable string describing the procedure's parameters. /// </summary> protected String GetParametersListDescription() { if (mProcedure == null) { return(""); } StringBuilder sb = new StringBuilder(); List <String> arguments = mProcedure.Arguments; if (arguments.Count > 0) { sb.Append(I18n.Get(MsgDefine.PROCEDURES_BEFORE_PARAMS)); for (int i = 0; i < arguments.Count; ++i) { sb.Append(i == 0 ? " " : ", "); sb.Append(arguments[i]); } } return(sb.ToString()); }
/// <summary> /// Performs the model changes for the given count. This will reuse as many inputs as possible, /// creating new inputs if necessary. Leftover inputs will be disconnected and thrown away. /// </summary> private void UpdateInternal() { List <Input> oldInputs = new List <Input>(mBlock.InputList); List <Input> newInputs = new List <Input>(); // Set aside the else input for the end. Input elseInput = mBlock.GetInput(ELSE_INPUT_NAME); if (elseInput != null) { oldInputs.Remove(elseInput); } // Move the first if/do block into the new input list newInputs.Add(oldInputs[0]); //IF0 newInputs.Add(oldInputs[1]); //DO0 oldInputs.RemoveRange(0, 2); // Copy over existing inputs if we have them, make new ones if we don't. for (int i = 1; i <= mElseIfCount; i++) { if (oldInputs.Count >= 2) { newInputs.Add(oldInputs[0]); //IFi newInputs.Add(oldInputs[1]); //DOi oldInputs.RemoveRange(0, 2); } else { // IFi value input Input inputValue = InputFactory.Create(Define.EConnection.InputValue, IF_INPUT_PREFIX + i, ALIGN, new List <string>() { CHECK }); inputValue.AppendField(new FieldLabel(null, I18n.Get(MsgDefine.CONTROLS_IF_MSG_ELSEIF))); // DOi statement input Input inputStatement = InputFactory.Create(Define.EConnection.NextStatement, DO_INPUT_PREFIX + i, ALIGN, null); inputStatement.AppendField(new FieldLabel(null, I18n.Get(MsgDefine.CONTROLS_IF_MSG_THEN))); newInputs.Add(inputValue); newInputs.Add(inputStatement); } } // Add the else clause if we need it if (mHasElse) { if (elseInput == null) { elseInput = InputFactory.Create(Define.EConnection.NextStatement, ELSE_INPUT_NAME, ALIGN, null); elseInput.AppendField(new FieldLabel(null, I18n.Get(MsgDefine.CONTROLS_IF_MSG_ELSE))); } newInputs.Add(elseInput); } else if (elseInput != null) { // dispose the else statement elseInput.Dispose(); } // Clean up extra inputs foreach (Input input in oldInputs) { input.Dispose(); } oldInputs.Clear(); mBlock.Reshape(newInputs); }
/// <summary> /// Internal implemention of the message reference and interpolation token /// Parsing used by tokenizeInterpolation() and replaceMessageReferences(). /// </summary> public static List <string> TokenizeInterpolation(string message, bool parseInterpolationTokens = true) { var tokens = new List <string>(); var chars = message.ToCharArray().ToList(); // Parse the message with a finite state machine. // 0 - Base case. // 1 - % found // 2 - Digit found. // 3 - Message ref found var state = 0; var buffer = new List <string>(); string number = ""; for (var i = 0; i < chars.Count + 1; i++) { var c = i == chars.Count ? ' ' : chars[i]; if (state == 0 && i != chars.Count) { if (c == '%') { var text = string.Join("", buffer.ToArray()); if (!string.IsNullOrEmpty(text)) { tokens.Add(text); } buffer.Clear(); state = 1; // Start escape. } else { buffer.Add(c.ToString()); // Regular char } } else if (state == 1) { if (c == '%') { buffer.Add(c.ToString()); // Escaped %: %% state = 0; } else if (parseInterpolationTokens && '0' <= c && c <= '9') { state = 2; number = c.ToString(); buffer.Add(""); var text = string.Join("", buffer.ToArray()); if (!string.IsNullOrEmpty(text)) { tokens.Add(text); } buffer.Clear(); } else if (c == '{') { state = 3; } else { buffer.Add("%"); // Not recognized. Return as literal. if (i != chars.Count) { buffer.Add(c.ToString()); } state = 0; // add parse as string literl } } else if (state == 2) { if ('0' <= c && c <= '9') { number += c; // Multi-digit number. } else { tokens.Add(int.Parse(number).ToString()); i--; // Parse this char agian. state = 0; } } else if (state == 3) { if (i == chars.Count) { // Premature end before closing '}' buffer.Insert(0, "%{"); // Re-insert leading delimiter i--; // Parse this char again. state = 0; // add parse as string literal. } else if (c != '}') { buffer.Add(c.ToString()); } else { var rawKey = string.Join("", buffer.ToArray()); if (new Regex("[a-zA-Z][a-zAZ0-9_]").Match(rawKey).Success) // Strict matching { // Found a valied string key. Attempt case insensitive match. var keyUpper = rawKey.ToUpper(); // BKY_ is the prefix used to namespace the string s used in Blockly // core files adn the predefined blocks in ../blocks/. These strings // are defined in ../msgs/ files. var bklyKey = keyUpper.StartsWith("BKY_") ? keyUpper.Substring(4) : null; if (!string.IsNullOrEmpty(bklyKey) && I18n.Contains(bklyKey)) { var rawValue = I18n.Get(bklyKey); tokens.AddRange(TokenizeInterpolation(rawValue)); } else { tokens.Add("%{" + rawKey + "}"); } buffer.Clear(); // Clear the array state = 0; } else { tokens.Add("%{" + rawKey + "}"); buffer.Clear(); state = 0; // and parse as string literal. } } } } var text1 = string.Join("", buffer.ToArray()); if (!string.IsNullOrEmpty(text1)) { tokens.Add(text1); } // Merge adjacent text tokens into a single string. var mergedTokens = new List <string>(); buffer.Clear(); for (int i = 0; i < tokens.Count; i++) { int tokenNum = 0; if (int.TryParse(tokens[i], out tokenNum)) { text1 = string.Join("", buffer.ToArray()); if (!string.IsNullOrEmpty(text1)) { mergedTokens.Add(text1); } buffer.Clear(); mergedTokens.Add(tokens[i]); } else { buffer.Add(tokens[i]); } } text1 = string.Join("", buffer.ToArray()); if (!string.IsNullOrEmpty(text1)) { mergedTokens.Add(text1); } buffer.Clear(); // remove last return(mergedTokens); }