/// <summary> /// Handles the end of the syntactical analisys process. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="args"> /// A <see cref="EventArgs"/> /// </param> private void OnControllerProcessFinishedHandler(object sender, EventArgs args) { Application.Invoke(delegate(object resender, EventArgs a) { if (controller.ParsingResult) { OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Info, "¡El proceso de análisis sintáctico fue un éxito!"); parsingShowOutputBtn.Sensitive = true; parsingProcessBtn.Sensitive = false; currentNode.SetOutput(controller.Output); } else { OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Warning, "El proceso de análisis sintáctico no tuvo éxito."); } parsingTaskLabel.Markup = "-"; parsingButtonsNB.Page = 0; }); }
private void OnParsingControllerProcessFinished(object sender, EventArgs args) { Application.Invoke(delegate(object resender, EventArgs a) { unassistedGlobalProgressBar.Fraction = 1; unassistedTaskProgressBar.Fraction = 0; unassistedTaskNameLabel.Text = "-"; MainRecognizerWindow.ProcessItemsSensitive = true; if (parsingController.ParsingResult) { OkDialog.Show(MainRecognizerWindow.Window, MessageType.Info, "¡El proceso de reconocimiento tuvo éxito!"); unassistedShowOutputBtn.Sensitive = true; } else { OkDialog.Show(MainRecognizerWindow.Window, MessageType.Warning, "¡El proceso de reconocimiento no tuvo éxito!"); } unassistedControlHBB.Sensitive = true; }); }
private void OpenDatabase() { // Preguntamos si se quiere salvar lo actual. SaveDatabase(); // Abrimos la base de datos. string file; if (DatabaseOpenDialog.Show(mainWindow, out file) == ResponseType.Ok) { // El usuario acepta la apertura del archivo. MathTextDatabase database = MathTextDatabase.Load(file); if (database == null) { // No se abrio un archivo de base de datos, informamos. OkDialog.Show(this.mainWindow, MessageType.Warning, "El archivo «{0}» no contiene una base de datos " + "correcta, y no se pudo abrir.", file); return; } SetDatabase(database); SetTitle(file); databaseModified = false; LogLine("¡Base de datos «" + file + "» cargada correctamente!"); } }
/// <summary> /// Edits the currently selected row of the treeview. /// </summary> /// <param name="iter"> /// The iter to be modified. /// </param> private bool EditIter(TreeIter selected) { SymbolLabelListDialog dialog = new SymbolLabelListDialog(this.symbolLabelDialog); dialog.Symbol = (string)(symbolLabelsModel.GetValue(selected, 0)); dialog.Label = (string)(symbolLabelsModel.GetValue(selected, 1)); ResponseType res; while ((res = dialog.Show()) == ResponseType.Ok && (String.IsNullOrEmpty(dialog.Label) || String.IsNullOrEmpty(dialog.Symbol))) { OkDialog.Show(this.symbolLabelDialog, MessageType.Warning, "Debe rellenar tanto el símbolo como la etiqueta"); } dialog.Destroy(); if (res == ResponseType.Ok) { symbolLabelsModel.SetValue(selected, 0, dialog.Symbol); symbolLabelsModel.SetValue(selected, 1, dialog.Label); changes = true; return(true); } else { return(false); } }
/// <summary> /// Checks if the tokeninzing result is correct, and if so, advances /// to the next /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="arg"> /// A <see cref="EventArgs"/> /// </param> private void OnNextStageBtnClicked(object sender, EventArgs arg) { List <string> errors = new List <string>(); foreach (SequenceNode rootNode in sequencesModel) { errors.AddRange(CheckNodeErrors(rootNode)); } if (errors.Count > 0) { // There were errors. string errorss = String.Join("\n", errors.ToArray()); OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Info, "Para continuar a la siguente fase de procesado, debes solucionar los siguentes problemas:\n\n{0}", errorss); } else { MainRecognizerWindow.CreateParsingWidget(); this.NextStage(); } }
private void OnSynRulesInfoBtnClicked(object sender, EventArgs args) { // TODO: Add a useful info message for the SyntacticalRulesManagerDialog. OkDialog.Show(this.syntacticalRulesManagerDialog, MessageType.Info, "Meeeeeeeeh!"); syntacticalRulesManagerDialog.Respond(ResponseType.None); }
/// <summary> /// Shows a message box with info about the dialog. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="args"> /// A <see cref="EventArgs"/> /// </param> private void OnInfoBtnClicked(object sender, EventArgs args) { OkDialog.Show(this.lexicalRuleEditorDialog, MessageType.Info, "Aquí puedes editar una regla de análisis léxico. En la " + "zona izquierda se establece el nombre de la regla (que" + " será el tipo del item creado a partir de la misma) y" + " en la zona derecha el conjunto de expresiones que la" + " generarán."); }
/// <summary> /// Shows an info messagebox for the dialog. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="args"> /// A <see cref="EventArgs"/> /// </param> private void OnInfoBtnClicked(object sender, EventArgs args) { OkDialog.Show(this.lexicalRulesManagerDialog, MessageType.Info, "Aquí puedes editar la lista de reglas léxicas que " + "se usarán para asignar etiquetas a los símbolos " + "según su significado.\n" + "Las reglas que estén más altas en la lista se aplicarán" + " primero, y esto puede influir en el resultado del" + " proceso de reconocimiento léxico."); }
/// <summary> /// Launches the save as dialog. /// </summary> /// <returns> /// The path the file was saved into, if any. /// </returns> private string SaveDatabaseAs() { string file; if (DatabaseSaveDialog.Show(mainWindow, out file) == ResponseType.Ok) { string ext = Path.GetExtension(file); if (!(ext == ".xml" || ext == ".XML" || ext == ".jilfml" || ext == ".JILFML")) { file += ".jilfml"; } bool save = true; if (File.Exists(file) && ConfirmDialog.Show( mainWindow, "El archivo «{0}» ya existe. ¿Deseas sobreescibirlo?", Path.GetFileName(file)) == ResponseType.No) { // No queremos sobreescribir un archivo existente. save = false; } if (save) { database.Save(file); OkDialog.Show( mainWindow, MessageType.Info, "Base de datos guardada correctamente en «{0}»", Path.GetFileName(file)); LogLine( "¡Base de datos guardada con éxito en «{0}»!", Path.GetFileName(file)); return(file); } } return(""); }
/// <summary> /// Indicates if the dialog has validation errors, and shows them. /// </summary> /// <returns> /// A <see cref="System.Boolean"/> /// </returns> private bool HasErrors() { if (choosenDatabase == null && !newRB.Active) { OkDialog.Show(learnSymbolDatabaseChooserDialog, MessageType.Warning, "Debes seleccionar una opción para continuar."); return(true); } return(false); }
/// <summary> /// Maneja el uso del boton de añadir las imagenes de una carpeta. /// </summary> private void OnAddFolderButtonClicked(object o, EventArgs a) { // Selccionamos la carpeta string folderPath; if (FolderOpenDialog.Show(this.Assistant.Window, out folderPath) == ResponseType.Ok) { int added = 0; string [] extensions = new string [] { "*.jpg", "*.JPG", "*.png", "*.PNG" }; foreach (string extension in extensions) { foreach (string file in Directory.GetFiles(folderPath, extension)) { // Si es png o jpg intentamos añadirlo. try { AddImageFile(file); added++; } catch (Exception) { // Si peta, el fichero tenia una extensión que no // hacia honor a su contenido. } } } if (added > 0) { // Decimos el número de archivos que hemos añadido. OkDialog.Show( this.Assistant.Window, MessageType.Info, "Se añidieron {0} archivos(s) de imagen.", added); } else { // Nos quejamos si no pudimos añadir ningún fichero. OkDialog.Show( this.Assistant.Window, MessageType.Warning, "No se encotró ningún archivo de imagen válido en la" + " carpeta seleccionada", added); } } }
private void OnTokenizingControllerProcessFinished(object sender, EventArgs args) { Application.Invoke(delegate(object resender, EventArgs a) { if (!tokenizingFinished) { tokenizingFinished = true; unassistedTaskNameLabel.Text = "Análisis léxico"; unassistedGlobalProgressBar.Fraction = 0.5; tokenizingController.Next(ControllerStepMode.UntilEnd); } else { List <Token> result = tokenizingController.Result; bool fail = false; foreach (Token t in result) { if (t == null) { fail = true; break; } } if (fail) { OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Warning, "El análisis léxico falló, hubo ítems que no concordaron con ninguna regla léxica.\nPrueba a añadir más reglas léxicas y vuelve a intentarlo."); unassistedControlHBB.Sensitive = true; return; } unassistedTaskNameLabel.Text = "Análisis sintáctico"; unassistedGlobalProgressBar.Fraction = 0.66; SyntacticalRulesLibrary.Instance.ClearRules(); foreach (SyntacticalRule rule in Config.RecognizerConfig.Instance.SyntacticalRules) { SyntacticalRulesLibrary.Instance.AddRule(rule); } SyntacticalRulesLibrary.Instance.StartRule = Config.RecognizerConfig.Instance.SyntacticalRules[0]; parsingController.SetStartTokens(result); parsingController.Next(ControllerStepMode.UntilEnd); } }); }
/// <summary> /// Validates the dialog, and responds accordignly. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="args"> /// A <see cref="EventArgs"/> /// </param> private void OnItemOpOkBtnClicked(object sender, EventArgs args) { List <string> errors = new List <string>(); if (itemOpFormatAlignment.Visible) { if (String.IsNullOrEmpty(itemOpFormatEntry.Text)) { errors.Add("· No hay definida cadena de formato para el item."); } List <string> checkList = new List <string>(); // The checking string has to contemplate the token the /// expresions are related to (hence the +1) for (int i = 0; i < itemOpRelatedItemsBox.Children.Length + 1; i++) { checkList.Add("test"); } try { String.Format(itemOpFormatEntry.Text, checkList.ToArray()); } catch (Exception) { errors.Add("· La cadena de formato para el item no es válida."); } foreach (RelatedItemWidget relatedWidget in itemOpRelatedItemsBox.Children) { errors.AddRange(relatedWidget.CheckErrors()); } } if (errors.Count > 0) { OkDialog.Show(this.expressionItemOptionsDialog, MessageType.Info, "Para continuar, debes solucionar los siguientes errores:\n\n{0}", String.Join("\n", errors.ToArray())); this.itemOpRelatedItemsScroller.QueueDraw(); this.expressionItemOptionsDialog.Respond(ResponseType.None); } else { this.expressionItemOptionsDialog.Respond(ResponseType.Ok); } }
private void OnOCRControllerProcessFinished(object sender, EventArgs args) { Application.Invoke(delegate(object resender, EventArgs a) { unassistedGlobalProgressBar.Fraction = 0.33; unassistedTaskNameLabel.Text = "Secuenciación"; List <Token> startTokens = new List <Token>(); foreach (SegmentedNode node in ocrController.Result) { if (node.Symbols.Count != 1) { SymbolLabelEditorDialog dialog = new SymbolLabelEditorDialog(this.MainRecognizerWindow.Window, node); ResponseType res = dialog.Show(); string label = dialog.Label; dialog.Destroy(); if (res == ResponseType.Ok) { node.Symbols.Clear(); node.Symbols.Add(new MathSymbol(label)); node.SetLabels(); } else { OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Error, "La fase de reconocimiento y segementado de imágenes falló."); unassistedControlHBB.Sensitive = true; return; } } startTokens.Add(new Token(node.Label, node.MathTextBitmap.Position.X, node.MathTextBitmap.Position.Y, node.MathTextBitmap.FloatImage)); } tokenizingFinished = false; tokenizingController.SetLexicalRules(Config.RecognizerConfig.Instance.LexicalRules); tokenizingController.SetInitialData(startTokens, null); tokenizingController.Next(ControllerStepMode.UntilEnd); }); }
private void OnSynEdOkBtnClicked(object sender, EventArgs args) { List <string> errors = new List <string>(); string ruleName = synEdRuleNameEntry.Text.Trim(); if (String.IsNullOrEmpty(ruleName)) { errors.Add("· No se ha establecido un nombre para la regla"); } else if (!editing || oldRuleName != ruleName) { if (manager.ExistsRuleName(ruleName)) { errors.Add("· Ya existe una regla con el nombre usado."); } } if (synEdExpressionsVB.Children.Length == 0) { errors.Add("· No se ha definido ninguna expresión para la regla."); } else { foreach (SyntacticalExpressionWidget widget in synEdExpressionsVB.Children) { List <string> expressionErrors = widget.CheckErrors(); errors.AddRange(expressionErrors); } } if (errors.Count > 0) { // There were validations errors, we inform the user. string errorString = String.Join("\n", errors.ToArray()); OkDialog.Show(this.Window, MessageType.Info, "Para continuar, debes solventar los siguientes errores:\n\n{0}", errorString); syntacticalRuleEditorDialog.Respond(ResponseType.None); synEdExpressionScroller.QueueDraw(); } else { syntacticalRuleEditorDialog.Respond(ResponseType.Ok); } }
private void OnOkBtnClicked(object e, EventArgs a) { if (selectedProcess != null) { // Salimos aceptando. processSelectorDialog.Respond(ResponseType.Ok); } else { OkDialog.Show(processSelectorDialog, MessageType.Info, "Debe seleccionar el tipo de proceso a añadir."); processSelectorDialog.Respond(ResponseType.None); } }
private void SymbolLearned() { Application.Invoke(delegate(object sender, EventArgs args) { ResetWidgets(); string msg = "!Símbolo aprendido con éxito!"; SetModified(true); LogLine(msg); OkDialog.Show(mainWindow, MessageType.Info, msg); PrepareForNewImage(); }); }
/// <summary> /// Añade una base de datos a la lista. /// </summary> /// <param name="databasePath"> /// La ruta de la base de datos. /// </param> private void AddDatabase(string databasePath) { MathTextDatabase database = MathTextDatabase.Load(databasePath); if (database == null) { // No se abrio un archivo de base de datos, informamos. OkDialog.Show(this.databaseManagerDialog, MessageType.Warning, "El archivo «{0}» no contiene una base de datos correcta, y no se pudo abrir.", databasePath); return; } DatabaseFileInfo databaseInfo = new DatabaseFileInfo(); databaseInfo.Database = database; databaseInfo.Path = databasePath; if (!databaseFilesInfo.Contains(databaseInfo)) { // Lo añadimos a la coleccion. databaseFilesInfo.Add(databaseInfo); TreeIter newItem = databasesLS.AppendValues(Path.GetFileName(databasePath), database.DatabaseTypeShortDescription, databasePath, databaseInfo); // Seleccionamos la fila añadida. databasesTV.Selection.SelectIter(newItem); TreePath newPath = databasesLS.GetPath(newItem); databasesTV.ScrollToCell(newPath, databasesTV.Columns[0], true, 1.0f, 0.0f); } else { OkDialog.Show(this.databaseManagerDialog, MessageType.Info, "La base de datos del fichero «{0}» ya se encuentra en la lista y no se añadirá de nuevo.", Path.GetFileName(databasePath)); } }
private void OnOkButtonClicked(object sender, EventArgs args) { if (String.IsNullOrEmpty(this.Label)) { // If there are errors, we show a message box and respond none, // so the dialog don't get closed. OkDialog.Show(this.symbolLabelEditorDialog, MessageType.Info, "Debes escribir una etiqueta para continuar."); symbolLabelEditorDialog.Respond(ResponseType.None); } else { symbolLabelEditorDialog.Respond(ResponseType.Ok); } }
/// <summary> /// Metodo que gestiona el evento que se provoca al hacer /// click en el boton "Aprender" de la interfaz. /// </summary> private void OnBtnLearnClicked(object sender, EventArgs arg) { string errorMsg = ""; symbol = new MathSymbol(); if (symbolLabelEditor.Label.Trim() == "") { errorMsg = ".- El texto del símbolo no es válido.\n"; } else { symbol.Text = symbolLabelEditor.Label.Trim(); } if (errorMsg == "") { //NO hay errores de validación nextButtonsHB.Sensitive = true; hboxSymbolWidgets.Sensitive = false; menuDatabase.Sensitive = false; menuSaveAs.Sensitive = false; menuOpen.Sensitive = false; learningThread = null; toolbar.Sensitive = false; learningThread = new Thread(new ThreadStart(LearnProccess)); learningThread.Start(); learningThread.Suspend(); return; } else { //Informamos de que no podemos aprender el caracter. OkDialog.Show( mainWindow, MessageType.Error, "El símbolo no puede ser aprendido porque:\n\n{0}", errorMsg); LogLine(errorMsg); } }
/// <summary> /// Añade la informacion de una base de datos a la lista. /// </summary> /// <param name="databaseInfo"> /// La informacion de base de datos a añadir. /// </param> private void AddDatabaseInfo(DatabaseFileInfo databaseInfo) { if (databaseInfo.Database == null) { // No se abrio un archivo de base de datos, informamos. OkDialog.Show(this.databaseManagerDialog, MessageType.Warning, "El archivo «{0}» no existe o no contiene una base de datos correcta, y no se pudo abrir.", databaseInfo.Path); return; } databaseFilesInfo.Add(databaseInfo); databasesLS.AppendValues(Path.GetFileName(databaseInfo.Path), databaseInfo.Database.DatabaseTypeShortDescription, databaseInfo.Path, databaseInfo); }
/// <summary> /// Manejo del evento provocado por el controlador cuando finaliza el /// proceso de reconocimiento. /// </summary> /// <param name="sender">El objeto que provoca el evento.</param> /// <param name="arg">Los argumentos del evento.</param> private void OnControllerProcessFinished(object sender, EventArgs arg) { // Llamamos a través de invoke para que funcione. Gtk.Application.Invoke(delegate(object resender, EventArgs args) { OkDialog.Show( MainRecognizerWindow.Window, MessageType.Info, "¡Proceso de segmentado y OCR terminado!\n" + "Ahora puede revisar el resultado."); ResetState(); recognizementFinished = true; gotoTokenizerBtn.Sensitive = true; }); }
/// <summary> /// /// </summary> /// <returns> /// A <see cref="System.Boolean"/> /// </returns> private bool CheckRules() { List <string> ruleNames = new List <string>(); List <SyntacticalRule> rules = this.SyntacticalRules; foreach (SyntacticalRule rule in rules) { ruleNames.Add(rule.Name); } List <string> errors = new List <string>(); foreach (SyntacticalRule rule in rules) { foreach (string usedRule in rule.RulesUsed) { if (!ruleNames.Contains(usedRule)) { errors.Add(String.Format("· La regla «{0}» usada en la regla «{1}» no existe.", usedRule, rule.Name)); } } } if (errors.Count > 0) { string errorMessage = "No se puede continuar porque se encontraron los siguientes errores en las reglas:\n\n{0}"; OkDialog.Show(this.syntacticalRulesManagerDialog, MessageType.Warning, errorMessage, String.Join("\n", errors.ToArray())); return(true); } return(false); }
/// <summary> /// Asks the user for confirmation and then saves a modified database. /// </summary> private void SaveDatabase() { if (databaseModified) { ResponseType res = ConfirmDialog.Show(mainWindow, "¿Quieres guardar " + "los cambios de la base de datos?"); if (res == ResponseType.Yes) { if (!String.IsNullOrEmpty(databasePath)) { // We save the database in the same path as it was loaded. database.Save(databasePath); SetModified(false); OkDialog.Show( mainWindow, MessageType.Info, "Base de datos guardada correctamente en «{0}»", Path.GetFileName(databasePath)); LogLine( "¡Base de datos guardada con éxito en «{0}»!", Path.GetFileName(databasePath)); } else { // If it is a new database, we make use the save as method. string path = SaveDatabaseAs(); if (!String.IsNullOrEmpty(path)) { SetTitle(path); SetModified(false); } } } } }
private void LearningProcessFailed(MathSymbol symbol) { Application.Invoke(this, new LearningFailedArgs(symbol), delegate(object sender, EventArgs a) { string msg = String.Format("¡Ya hay un símbolo, «{0}», con las mismas propiedades en la base de datos!", (a as LearningFailedArgs).DuplicateSymbol); LogLine(msg); ResetWidgets(); // There were a conflict. conflicts++; OkDialog.Show(mainWindow, MessageType.Error, msg); PrepareForNewImage(); }); }
/// <summary> /// Checks the dialog's widget for validation errors and shows a /// message if errors are found. /// </summary> /// <returns> /// A <see cref="System.Boolean"/> /// </returns> private bool HasErrors() { List <string> errors = new List <string>(); if (outSettingsShowOutputCheck.Active) { // We have to check the command. string command = outSettingsCommandEntry.Text.Trim(); if (String.IsNullOrEmpty(command)) { errors.Add("· No se especificó un comando para generar una imagen."); } else if (!command.Contains("{0}") || !command.Contains("{1}")) { errors.Add("· No se encontraron en el comando especificado los dos elementos por los que se reemplazarán los archivos temporales necesarios para generar la imagen ({0} y {1})"); } try { String.Format(command, "input", "output"); } catch (Exception) { errors.Add("· El comando especificado no tiene un formato válido."); } } if (errors.Count > 0) { OkDialog.Show(this.outputSettingsDialog, MessageType.Warning, "Para continuar, debes solucionar los siguientes errores:\n\n{0}", String.Join("\n", errors.ToArray())); return(true); } return(false); }
/// <summary> /// Handles the click on the "go to tokenizer" button. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> /// </param> /// <param name="arg"> /// A <see cref="EventArgs"/> /// </param> private void OnGoToTokenizerBtnClicked(object sender, EventArgs arg) { // We have to check the leaf nodes for problems. SegmentedNode analizedNode = rootNode; List <string> errors = CheckErrors(); if (errors.Count == 0) { MainRecognizerWindow.CreateTokenizingWidget(); NextStage(); } else { string errorss = String.Join("\n", errors.ToArray()); OkDialog.Show(this.MainRecognizerWindow.Window, MessageType.Info, "Para continuar a la siguente fase de procesado," + "debes solucionar los siguentes problemas:\n\n{0}", errorss); } }
/// <summary> /// Muestra una venta de información para el archivo representado /// por un icono de la vista de archivos. /// </summary> private void FilesIconViewItemActivated() { if (filesIconView.SelectedItems.Length > 0) { // Recuperamos el elemento del IconView que se ha seleccionado TreeIter iter; fileStore.GetIter(out iter, filesIconView.SelectedItems[0]); // Recuperamos el archivo asociado al icono string filepath = fileStore.GetValue(iter, 2) as string; Gdk.Pixbuf p = new Gdk.Pixbuf(filepath); // Mostramos la ventana de informacióndel archivo OkDialog.Show( this.Assistant.Window, MessageType.Info, "Información de «{0}»:\n\n" + "· Ruta del archivo: {1}\n" + ". Tamaño de la imagen: " + p.Width + " x " + p.Height + "\n", fileStore.GetValue(iter, 1) as string, Path.GetDirectoryName(filepath)); } }
private void OnCloseBtnClicked(object sender, EventArgs args) { List <string> errors = new List <string>(); if (String.IsNullOrEmpty(ShortDescription)) { errors.Add("· Debes escribir una descripción corta."); } if (String.IsNullOrEmpty(LongDescription)) { errors.Add("· Debes escribir una descripción larga."); } if (errors.Count > 0) { // We found errors and have to inform the user. string errorMsg = ""; foreach (string error in errors) { errorMsg += String.Format("{0}\n", error); } OkDialog.Show(databaseDescriptionEditorDialog, MessageType.Warning, "Para continuar, tienes que solucionar los " + "siguientes problemas:\n\n{0}", errorMsg); databaseDescriptionEditorDialog.Respond(ResponseType.None); } else { databaseDescriptionEditorDialog.Respond(ResponseType.Ok); } }
/// <summary> /// Muestra el mensaje que indica como termino el proceso de aprendizaje, /// e inicicializa contadores y otras variables relacionadas /// con el proceso de aprendizaje actual. /// </summary> private void AllImagesLearned() { string conflictsMessage = ""; // Generamos la cadena que informa de los conflictos switch (conflicts) { case 0: break; case 1: conflictsMessage = "Hubo un conflicto entre caracteres."; break; default: conflictsMessage = String.Format("Hubo {0} conflictos entre caracteres.", conflicts); break; } // Informamos al usuario. OkDialog.Show(mainWindow, MessageType.Info, "Todos los caracteres fueron procesados.\n{0}", conflictsMessage); mtb = null; // Reinciamos el contador de conflictos. conflicts = 0; nextImageBtn.Sensitive = false; imagesVB.Sensitive = true; }