271 lines
11 KiB
C#
271 lines
11 KiB
C#
using DataModel.Database;
|
|
using Processor;
|
|
using UI_WinForms.Dialogs;
|
|
using UI_WinForms.Resources;
|
|
|
|
namespace UI_WinForms.Components;
|
|
|
|
public partial class TextElements : UserControl
|
|
{
|
|
private Section? currentSection;
|
|
private TextElement? currentTextElement;
|
|
|
|
public TextElements()
|
|
{
|
|
this.InitializeComponent();
|
|
|
|
// Check if we are in the designer:
|
|
if(Program.SERVICE_PROVIDER is null)
|
|
return;
|
|
|
|
// Create an image list from a resource:
|
|
var imgList = new ImageList();
|
|
imgList.ImageSize = new Size(45, 45);
|
|
imgList.ColorDepth = ColorDepth.Depth32Bit;
|
|
imgList.Images.Add(Icons.icons8_row_512);
|
|
imgList.Images.Add(Icons.icons8_align_text_left_512);
|
|
|
|
// Set the image list to the list box:
|
|
this.listTextElements.SmallImageList = imgList;
|
|
|
|
// When the section is changed, update this component:
|
|
AppEvents.WhenSectionChanged += async (sender, section) =>
|
|
{
|
|
this.currentSection = section;
|
|
this.currentTextElement = null;
|
|
this.buttonAdd.Enabled = this.currentSection is not null;
|
|
this.buttonRename.Enabled = this.buttonRemove.Enabled = this.buttonChangeMultiLine.Enabled = this.buttonCopyKey.Enabled = false;
|
|
|
|
if (this.currentSection is null)
|
|
return;
|
|
|
|
// Update the path:
|
|
this.labelSectionPath.Text = await SectionProcessor.GetSectionPath(this.currentSection.DataKey);
|
|
await this.LoadTextElements();
|
|
};
|
|
|
|
// When the text element is changed, update the button states:
|
|
AppEvents.WhenTextElementChanged += (sender, textElement) =>
|
|
{
|
|
this.currentTextElement = textElement;
|
|
this.buttonRename.Enabled = this.buttonRemove.Enabled = this.buttonChangeMultiLine.Enabled = this.buttonCopyKey.Enabled = this.currentTextElement is not null;
|
|
|
|
if (this.currentTextElement is not null && this.currentTextElement.IsMultiLine)
|
|
this.buttonChangeMultiLine.Image = Icons.icons8_row_512;
|
|
else
|
|
this.buttonChangeMultiLine.Image = Icons.icons8_align_text_left_512;
|
|
};
|
|
|
|
AppEvents.WhenTranslationChanged += async (_, translation) =>
|
|
{
|
|
if (translation is null)
|
|
return;
|
|
|
|
// Check if the translation is in the current text element.
|
|
// When this is the case, update the list view item. We want
|
|
// to update the progress part.
|
|
if (this.currentTextElement?.Translations.Any(n => n.Id == translation.Id) ?? false)
|
|
{
|
|
// Determine the translation progress:
|
|
var progress = await TranslationProcessor.CalculateTranslationProgress(this.currentTextElement);
|
|
|
|
if (this.listTextElements.InvokeRequired)
|
|
this.listTextElements.Invoke(UpdateListElement);
|
|
else
|
|
UpdateListElement();
|
|
|
|
void UpdateListElement()
|
|
{
|
|
// Get the list view item by searching the TAG property:
|
|
var item = this.listTextElements.Items.Cast<ListViewItem>().FirstOrDefault(n => n.Tag is int id && id == this.currentTextElement.Id);
|
|
if (item is null)
|
|
return;
|
|
|
|
// Update the progress text:
|
|
item.Text = $"{this.currentTextElement.Name} [{progress.Result}%]";
|
|
}
|
|
}
|
|
};
|
|
|
|
// When the user press Ctrl + C, copy the text element's key to the clipboard:
|
|
this.listTextElements.KeyDown += (sender, e) =>
|
|
{
|
|
if (e is {Control: true, KeyCode: Keys.C})
|
|
this.buttonCopyKey.PerformClick();
|
|
};
|
|
}
|
|
|
|
// Loads all the text elements for the current section.
|
|
private async Task LoadTextElements()
|
|
{
|
|
if (this.currentSection is null)
|
|
return;
|
|
|
|
// Load the text elements:
|
|
var textElements = await TextElementProcessor.GetTextElements(this.currentSection, this.textBoxFilter.Text);
|
|
|
|
// Update the list:
|
|
this.listTextElements.Items.Clear();
|
|
foreach (var textElement in textElements)
|
|
{
|
|
// Determine the translation progress:
|
|
var progress = await TranslationProcessor.CalculateTranslationProgress(textElement);
|
|
this.listTextElements.Items.Add(new ListViewItem($"{textElement.Name} [{progress.Result}%]", textElement.IsMultiLine ? 1 : 0)
|
|
{
|
|
Tag = textElement.Id,
|
|
});
|
|
}
|
|
|
|
this.column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
|
|
}
|
|
|
|
private async void buttonAdd_Click(object sender, EventArgs e)
|
|
{
|
|
if(this.DesignMode)
|
|
return;
|
|
|
|
var result = InputDialog.Show(new InputDialog.Options(
|
|
Message: "Please type the desired text element's name.",
|
|
Title: "Add a text element",
|
|
Placeholder: "My text element",
|
|
ShowQuestionCheckbox: true,
|
|
QuestionCheckboxText: "Is multi-line?"
|
|
));
|
|
|
|
if(result.DialogResult == DialogResult.Cancel)
|
|
return;
|
|
|
|
// Add the text element to the database into the current section:
|
|
var newTextElement = await TextElementProcessor.AddTextElement(this.currentSection?.DataKey, result.Text, result.AnswerToQuestion);
|
|
newTextElement.ProcessError();
|
|
|
|
if(!newTextElement.Successful)
|
|
return;
|
|
|
|
// Add the text element to the list:
|
|
this.listTextElements.Items.Add(new ListViewItem(newTextElement.Result!.Name, newTextElement.Result.IsMultiLine ? 1 : 0)
|
|
{
|
|
Tag = newTextElement.Result.Id,
|
|
});
|
|
|
|
this.column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
|
|
AppEvents.TranslationChanged(null);
|
|
}
|
|
|
|
private async void buttonRemove_Click(object sender, EventArgs e)
|
|
{
|
|
if(this.DesignMode || this.currentTextElement is null)
|
|
return;
|
|
|
|
// Ask the user, if he really wants to remove the text element:
|
|
if(MessageBox.Show(this.currentTextElement.Translations.Count > 0 ? $"Are you sure, you want to remove the text element '{this.currentTextElement.Name}', its {this.currentTextElement.Translations.Count} translations and so on?" : $"Are you sure, you want to remove the text element '{this.currentTextElement.Name}'?", "Remove text element", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
|
|
return;
|
|
|
|
// Remove the text element from the database:
|
|
await TextElementProcessor.DeleteTextElement(this.currentTextElement.Id);
|
|
|
|
// Reload the data:
|
|
await this.LoadTextElements();
|
|
AppEvents.TranslationChanged(null);
|
|
}
|
|
|
|
private async void buttonRename_Click(object sender, EventArgs e)
|
|
{
|
|
if(this.DesignMode)
|
|
return;
|
|
|
|
// Ask the user if he really wants to rename the text element:
|
|
if(MessageBox.Show("Are you sure, you want to rename the selected text element? If you are already using this element in your code, you will need to manually refactor your code after renaming it.", "Rename text element", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.No)
|
|
return;
|
|
|
|
// Ask the user for the new name:
|
|
var result = InputDialog.Show(new InputDialog.Options(
|
|
Message: "Please edit the text element's name.",
|
|
PreloadedText: this.currentTextElement!.Name,
|
|
ShowQuestionCheckbox: true,
|
|
Title: "Rename text element",
|
|
QuestionCheckboxText: "Is multi-line?",
|
|
QuestionCheckboxState: this.currentTextElement.IsMultiLine
|
|
));
|
|
|
|
// If the user canceled, return:
|
|
if(result.DialogResult == DialogResult.Cancel)
|
|
return;
|
|
|
|
ProcessorResult<TextElement> alteredTextElement;
|
|
if(this.currentTextElement.Name == result.Text)
|
|
// Update the multi-line state:
|
|
alteredTextElement = await TextElementProcessor.UpdateTextElementState(this.currentTextElement.Id, result.AnswerToQuestion);
|
|
else
|
|
// Rename the text element:
|
|
alteredTextElement = await TextElementProcessor.RenameTextElement(this.currentTextElement.Id, result.Text, result.AnswerToQuestion);
|
|
|
|
alteredTextElement.ProcessError();
|
|
if(!alteredTextElement.Successful)
|
|
return;
|
|
|
|
// Reload the text elements:
|
|
await this.LoadTextElements();
|
|
}
|
|
|
|
private async void buttonChangeMultiLine_Click(object sender, EventArgs e)
|
|
{
|
|
if(this.DesignMode)
|
|
return;
|
|
|
|
// Update the multi-line state:
|
|
var alteredTextElement = await TextElementProcessor.UpdateTextElementState(this.currentTextElement!.Id, !this.currentTextElement.IsMultiLine);
|
|
|
|
alteredTextElement.ProcessError();
|
|
if(!alteredTextElement.Successful)
|
|
return;
|
|
|
|
// Reload the text elements:
|
|
await this.LoadTextElements();
|
|
|
|
// Re-select the text element:
|
|
foreach (ListViewItem item in this.listTextElements.Items)
|
|
{
|
|
if ((int)item.Tag == this.currentTextElement.Id)
|
|
{
|
|
item.Selected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void listTextElements_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
|
|
{
|
|
if (e.IsSelected)
|
|
{
|
|
// Get the text element's id:
|
|
var selectedTextElementId = (int)e.Item.Tag;
|
|
|
|
// Load the text element:
|
|
this.currentTextElement = await TextElementProcessor.LoadTextElement(selectedTextElementId);
|
|
|
|
// Fire the event:
|
|
AppEvents.TextElementChanged(this.currentTextElement);
|
|
}
|
|
else
|
|
AppEvents.TextElementChanged(null);
|
|
}
|
|
|
|
private async void textBoxFilter_KeyUp(object sender, KeyEventArgs e) => await this.LoadTextElements();
|
|
|
|
private async void buttonCopyKey_Click(object sender, EventArgs e)
|
|
{
|
|
if(this.DesignMode || this.currentTextElement is null)
|
|
return;
|
|
|
|
Clipboard.SetText(await TextElementProcessor.GetKey(this.currentTextElement.Id));
|
|
|
|
//
|
|
// Switch the button's icon to the "ok" icon for a few
|
|
// seconds, to indicate, that the key was copied:
|
|
//
|
|
this.buttonCopyKey.Image = Icons.icons8_ok_512;
|
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
|
this.buttonCopyKey.Image = Icons.icons8_key2_512;
|
|
}
|
|
} |