Add undo and redo support for cells attribute.

This commit is contained in:
BDisp
2024-10-07 00:19:51 +01:00
parent d5e367b117
commit e58c15f2e6
12 changed files with 804 additions and 575 deletions

View File

@@ -72,8 +72,8 @@ public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Ru
public static List<List<Cell>> StringToLinesOfCells (string content, Attribute? attribute = null)
{
List<Cell> cells = content.EnumerateRunes ()
.Select (x => new Cell { Rune = x, Attribute = attribute })
.ToList ();
.Select (x => new Cell { Rune = x, Attribute = attribute })
.ToList ();
return SplitNewLines (cells);
}
@@ -93,6 +93,27 @@ public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Ru
return str;
}
/// <summary>Converts a <see cref="List{Cell}"/> generic collection into a string.</summary>
/// <param name="cellsList">The enumerable cell to convert.</param>
/// <returns></returns>
public static string ToString (List<List<Cell>> cellsList)
{
var str = string.Empty;
for (var i = 0; i < cellsList.Count; i++)
{
IEnumerable<Cell> cellList = cellsList [i];
str += ToString (cellList);
if (i + 1 < cellsList.Count)
{
str += Environment.NewLine;
}
}
return str;
}
// Turns the string into cells, this does not split the contents on a newline if it is present.
internal static List<Cell> StringToCells (string str, Attribute? attribute = null)

View File

@@ -173,4 +173,123 @@ public sealed class Colors : INotifyCollectionChanged, IDictionary<string, Color
return ColorSchemes;
}
/// <summary>
/// Open a <see cref="Dialog"/> with two <see cref="ColorPicker"/> or <see cref="ColorPicker16"/>, based on the
/// <see cref="ConsoleDriver.Force16Colors"/> is false or true, respectively, for <see cref="Attribute.Foreground"/>
/// and <see cref="Attribute.Background"/> colors.
/// </summary>
/// <param name="title">The title to show in the dialog.</param>
/// <param name="currentAttribute">The current attribute used.</param>
/// <param name="newAttribute">The new attribute.</param>
/// <returns><see langword="true"/> if a new color was accepted, otherwise <see langword="false"/>.</returns>
public static bool PromptForColors (string title, Attribute? currentAttribute, out Attribute newAttribute)
{
var accept = false;
var d = new Dialog
{
Title = title,
Width = Application.Force16Colors ? 37 : Dim.Auto (DimAutoStyle.Auto, Dim.Percent (80), Dim.Percent (90)),
Height = 20
};
var btnOk = new Button
{
X = Pos.Center () - 5,
Y = Application.Force16Colors ? 6 : 4,
Text = "Ok",
Width = Dim.Auto (),
IsDefault = true
};
btnOk.Accept += (s, e) =>
{
accept = true;
e.Handled = true;
Application.RequestStop ();
};
var btnCancel = new Button
{
X = Pos.Center () + 5,
Y = 4,
Text = "Cancel",
Width = Dim.Auto ()
};
btnCancel.Accept += (s, e) =>
{
e.Handled = true;
Application.RequestStop ();
};
d.Add (btnOk);
d.Add (btnCancel);
d.AddButton (btnOk);
d.AddButton (btnCancel);
View cpForeground;
if (Application.Force16Colors)
{
cpForeground = new ColorPicker16
{
SelectedColor = currentAttribute!.Value.Foreground.GetClosestNamedColor16 (),
Width = Dim.Fill (),
BorderStyle = LineStyle.Single,
Title = "Foreground"
};
}
else
{
cpForeground = new ColorPicker
{
SelectedColor = currentAttribute!.Value.Foreground,
Width = Dim.Fill (),
Style = new () { ShowColorName = true, ShowTextFields = true },
BorderStyle = LineStyle.Single,
Title = "Foreground"
};
((ColorPicker)cpForeground).ApplyStyleChanges ();
}
View cpBackground;
if (Application.Force16Colors)
{
cpBackground = new ColorPicker16
{
SelectedColor = currentAttribute!.Value.Background.GetClosestNamedColor16 (),
Y = Pos.Bottom (cpForeground) + 1,
Width = Dim.Fill (),
BorderStyle = LineStyle.Single,
Title = "Background"
};
}
else
{
cpBackground = new ColorPicker
{
SelectedColor = currentAttribute!.Value.Background,
Width = Dim.Fill (),
Y = Pos.Bottom (cpForeground) + 1,
Style = new () { ShowColorName = true, ShowTextFields = true },
BorderStyle = LineStyle.Single,
Title = "Background"
};
((ColorPicker)cpBackground).ApplyStyleChanges ();
}
d.Add (cpForeground, cpBackground);
Application.Run (d);
d.Dispose ();
Color newForeColor = Application.Force16Colors ? ((ColorPicker16)cpForeground).SelectedColor : ((ColorPicker)cpForeground).SelectedColor;
Color newBackColor = Application.Force16Colors ? ((ColorPicker16)cpBackground).SelectedColor : ((ColorPicker)cpBackground).SelectedColor;
newAttribute = new (newForeColor, newBackColor);
return accept;
}
}

View File

@@ -1437,6 +1437,15 @@ namespace Terminal.Gui.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Co_lors.
/// </summary>
internal static string ctxColors {
get {
return ResourceManager.GetString("ctxColors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Copy.
/// </summary>

View File

@@ -117,27 +117,27 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ctxSelectAll" xml:space="preserve">
<value>Tout _sélectionner</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>_Tout supprimer</value>
</data>
<data name="ctxCopy" xml:space="preserve">
<value>_Copier</value>
</data>
<data name="ctxCut" xml:space="preserve">
<value>Co_uper</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>_Tout supprimer</value>
</data>
<data name="ctxPaste" xml:space="preserve">
<value>C_oller</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>_Rétablir</value>
</data>
<data name="ctxSelectAll" xml:space="preserve">
<value>Tout _sélectionner</value>
</data>
<data name="ctxUndo" xml:space="preserve">
<value>_Annuler</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>_Rétablir</value>
</data>
<data name="fdDirectory" xml:space="preserve">
<value>_Dossier</value>
</data>
@@ -168,16 +168,19 @@
<data name="wzNext" xml:space="preserve">
<value>Prochai_n...</value>
</data>
<data name="btnOpen" xml:space="preserve">
<value>Ouvrir</value>
</data>
<data name="btnSave" xml:space="preserve">
<value>Enregistrer</value>
</data>
<data name="btnSaveAs" xml:space="preserve">
<value>E_nregistrer sous</value>
</data>
<data name="btnOpen" xml:space="preserve">
<value>Ouvrir</value>
</data>
<data name="dpTitle" xml:space="preserve">
<value>Sélecteur de Date</value>
</data>
<data name="ctxColors" xml:space="preserve">
<value>Cou_leurs</value>
</data>
</root>

View File

@@ -117,27 +117,27 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ctxSelectAll" xml:space="preserve">
<value>全て選択 (_S)</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>全て削除 (_D)</value>
</data>
<data name="ctxCopy" xml:space="preserve">
<value>コピー (_C)</value>
</data>
<data name="ctxCut" xml:space="preserve">
<value>切り取り (_T)</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>全て削除 (_D)</value>
</data>
<data name="ctxPaste" xml:space="preserve">
<value>貼り付け (_P)</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>やり直し (_R)</value>
</data>
<data name="ctxSelectAll" xml:space="preserve">
<value>全て選択 (_S)</value>
</data>
<data name="ctxUndo" xml:space="preserve">
<value>元に戻す (_U)</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>やり直し (_R)</value>
</data>
<data name="fdDirectory" xml:space="preserve">
<value>ディレクトリ</value>
</data>
@@ -171,80 +171,74 @@
<data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
<value>同じ名前のディレクトリはすでに存在しました</value>
</data>
<data name="fdDeleteBody" xml:space="preserve">
<value>“{0}”を削除もよろしいですか?この操作は元に戻りません</value>
</data>
<data name="fdType" xml:space="preserve">
<value>タイプ</value>
</data>
<data name="fdSize" xml:space="preserve">
<value>サイズ</value>
</data>
<data name="fdPathCaption" xml:space="preserve">
<value>パスを入力</value>
</data>
<data name="fdFilename" xml:space="preserve">
<value>ファイル名</value>
</data>
<data name="fdNewTitle" xml:space="preserve">
<value>新規ディレクトリ</value>
</data>
<data name="btnNo" xml:space="preserve">
<value>いいえ (_N)</value>
</data>
<data name="btnYes" xml:space="preserve">
<value>はい (_Y)</value>
</data>
<data name="fdModified" xml:space="preserve">
<value>変更日時</value>
</data>
<data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
<value>すでに存在したファイルまたはディレクトリを選択してください</value>
</data>
<data name="fdDirectoryMustExistFeedback" xml:space="preserve">
<value>すでに存在したディレクトリを選択してください</value>
</data>
<data name="fdFileMustExistFeedback" xml:space="preserve">
<value>すでに存在したファイルを選択してください</value>
</data>
<data name="fdRenamePrompt" xml:space="preserve">
<value>名前:</value>
</data>
<data name="fdDeleteTitle" xml:space="preserve">
<value>{0} を削除</value>
</data>
<data name="fdNewFailed" xml:space="preserve">
<value>新規失敗</value>
</data>
<data name="fdExisting" xml:space="preserve">
<value>既存</value>
</data>
<data name="fdRenameTitle" xml:space="preserve">
<value>名前を変更</value>
</data>
<data name="fdRenameFailedTitle" xml:space="preserve">
<value>変更失敗</value>
</data>
<data name="fdDeleteFailedTitle" xml:space="preserve">
<value>削除失敗</value>
</data>
<data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
<value>同じ名前のファイルはすでに存在しました</value>
</data>
<data name="fdFileMustExistFeedback" xml:space="preserve">
<value>すでに存在したファイルを選択してください</value>
</data>
<data name="fdFilename" xml:space="preserve">
<value>ファイル名</value>
</data>
<data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
<value>すでに存在したファイルまたはディレクトリを選択してください</value>
</data>
<data name="fdModified" xml:space="preserve">
<value>変更日時</value>
</data>
<data name="fdPathCaption" xml:space="preserve">
<value>パスを入力</value>
</data>
<data name="fdSearchCaption" xml:space="preserve">
<value>検索を入力</value>
</data>
<data name="fdSize" xml:space="preserve">
<value>サイズ</value>
</data>
<data name="fdType" xml:space="preserve">
<value>タイプ</value>
</data>
<data name="fdWrongFileTypeFeedback" xml:space="preserve">
<value>ファイルタイプが間違っでいます</value>
</data>
<data name="fdAnyFiles" xml:space="preserve">
<value>任意ファイル</value>
</data>
<data name="btnCancel" xml:space="preserve">
<value>キャンセル (_C)</value>
<data name="fdDeleteBody" xml:space="preserve">
<value>“{0}”を削除もよろしいですか?この操作は元に戻りません</value>
</data>
<data name="btnOk" xml:space="preserve">
<value>OK (_O)</value>
<data name="fdDeleteFailedTitle" xml:space="preserve">
<value>削除失敗</value>
</data>
<data name="fdDeleteTitle" xml:space="preserve">
<value>{0} を削除</value>
</data>
<data name="fdNewFailed" xml:space="preserve">
<value>新規失敗</value>
</data>
<data name="fdNewTitle" xml:space="preserve">
<value>新規ディレクトリ</value>
</data>
<data name="btnNo" xml:space="preserve">
<value>いいえ (_N)</value>
</data>
<data name="fdRenameFailedTitle" xml:space="preserve">
<value>変更失敗</value>
</data>
<data name="fdRenamePrompt" xml:space="preserve">
<value>名前:</value>
</data>
<data name="fdRenameTitle" xml:space="preserve">
<value>名前を変更</value>
</data>
<data name="btnYes" xml:space="preserve">
<value>はい (_Y)</value>
</data>
<data name="fdExisting" xml:space="preserve">
<value>既存</value>
</data>
<data name="btnOpen" xml:space="preserve">
<value>開く (_O)</value>
@@ -255,6 +249,12 @@
<data name="btnSaveAs" xml:space="preserve">
<value>名前を付けて保存 (_S)</value>
</data>
<data name="btnOk" xml:space="preserve">
<value>OK (_O)</value>
</data>
<data name="btnCancel" xml:space="preserve">
<value>キャンセル (_C)</value>
</data>
<data name="fdCtxDelete" xml:space="preserve">
<value>削除 (_D)</value>
</data>
@@ -276,4 +276,7 @@
<data name="dpTitle" xml:space="preserve">
<value>日付ピッカー</value>
</data>
<data name="ctxColors" xml:space="preserve">
<value>絵の具 (_L)</value>
</data>
</root>

View File

@@ -117,27 +117,27 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ctxSelectAll" xml:space="preserve">
<value>_Selecionar Tudo</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>_Apagar Tudo</value>
</data>
<data name="ctxCopy" xml:space="preserve">
<value>_Copiar</value>
</data>
<data name="ctxCut" xml:space="preserve">
<value>Cor_tar</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<value>_Apagar Tudo</value>
</data>
<data name="ctxPaste" xml:space="preserve">
<value>Co_lar</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>_Refazer</value>
</data>
<data name="ctxSelectAll" xml:space="preserve">
<value>_Selecionar Tudo</value>
</data>
<data name="ctxUndo" xml:space="preserve">
<value>_Desfazer</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<value>_Refazer</value>
</data>
<data name="fdDirectory" xml:space="preserve">
<value>Diretório</value>
</data>
@@ -168,16 +168,19 @@
<data name="wzNext" xml:space="preserve">
<value>S_eguir...</value>
</data>
<data name="btnSaveAs" xml:space="preserve">
<value>Guardar como</value>
<data name="btnOpen" xml:space="preserve">
<value>Abrir</value>
</data>
<data name="btnSave" xml:space="preserve">
<value>Guardar</value>
</data>
<data name="btnOpen" xml:space="preserve">
<value>Abrir</value>
<data name="btnSaveAs" xml:space="preserve">
<value>Guardar como</value>
</data>
<data name="dpTitle" xml:space="preserve">
<value>Seletor de Data</value>
</data>
<data name="ctxColors" xml:space="preserve">
<value>Co_res</value>
</data>
</root>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
<!--
Microsoft ResX Schema
Version 2.0
@@ -59,663 +59,666 @@
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ctxSelectAll" xml:space="preserve">
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ctxSelectAll" xml:space="preserve">
<value>_Select All</value>
</data>
<data name="ctxDeleteAll" xml:space="preserve">
<data name="ctxDeleteAll" xml:space="preserve">
<value>_Delete All</value>
</data>
<data name="ctxCopy" xml:space="preserve">
<data name="ctxCopy" xml:space="preserve">
<value>_Copy</value>
</data>
<data name="ctxCut" xml:space="preserve">
<data name="ctxCut" xml:space="preserve">
<value>Cu_t</value>
</data>
<data name="ctxPaste" xml:space="preserve">
<data name="ctxPaste" xml:space="preserve">
<value>_Paste</value>
</data>
<data name="ctxUndo" xml:space="preserve">
<data name="ctxUndo" xml:space="preserve">
<value>_Undo</value>
</data>
<data name="ctxRedo" xml:space="preserve">
<data name="ctxRedo" xml:space="preserve">
<value>_Redo</value>
</data>
<data name="fdDirectory" xml:space="preserve">
<data name="fdDirectory" xml:space="preserve">
<value>Directory</value>
</data>
<data name="fdFile" xml:space="preserve">
<data name="fdFile" xml:space="preserve">
<value>File</value>
</data>
<data name="fdSave" xml:space="preserve">
<data name="fdSave" xml:space="preserve">
<value>Save</value>
</data>
<data name="fdSaveAs" xml:space="preserve">
<data name="fdSaveAs" xml:space="preserve">
<value>Save as</value>
</data>
<data name="fdOpen" xml:space="preserve">
<data name="fdOpen" xml:space="preserve">
<value>Open</value>
</data>
<data name="fdSelectFolder" xml:space="preserve">
<data name="fdSelectFolder" xml:space="preserve">
<value>Select folder</value>
</data>
<data name="fdSelectMixed" xml:space="preserve">
<data name="fdSelectMixed" xml:space="preserve">
<value>Select Mixed</value>
</data>
<data name="wzBack" xml:space="preserve">
<data name="wzBack" xml:space="preserve">
<value>_Back</value>
</data>
<data name="wzFinish" xml:space="preserve">
<data name="wzFinish" xml:space="preserve">
<value>Fi_nish</value>
</data>
<data name="wzNext" xml:space="preserve">
<data name="wzNext" xml:space="preserve">
<value>_Next...</value>
</data>
<data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
<data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
<value>Directory already exists with that name</value>
<comment>When trying to save a file with a name already taken by a directory</comment>
</data>
<data name="fdDirectoryMustExistFeedback" xml:space="preserve">
<data name="fdDirectoryMustExistFeedback" xml:space="preserve">
<value>Must select an existing directory</value>
</data>
<data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
<data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
<value>File already exists with that name</value>
</data>
<data name="fdFileMustExistFeedback" xml:space="preserve">
<data name="fdFileMustExistFeedback" xml:space="preserve">
<value>Must select an existing file</value>
<comment>When trying to save a directory with a name already used by a file</comment>
</data>
<data name="fdFilename" xml:space="preserve">
<data name="fdFilename" xml:space="preserve">
<value>Filename</value>
</data>
<data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
<data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
<value>Must select an existing file or directory</value>
</data>
<data name="fdModified" xml:space="preserve">
<data name="fdModified" xml:space="preserve">
<value>Modified</value>
</data>
<data name="fdPathCaption" xml:space="preserve">
<data name="fdPathCaption" xml:space="preserve">
<value>Enter Path</value>
</data>
<data name="fdSearchCaption" xml:space="preserve">
<data name="fdSearchCaption" xml:space="preserve">
<value>Enter Search</value>
</data>
<data name="fdSize" xml:space="preserve">
<data name="fdSize" xml:space="preserve">
<value>Size</value>
</data>
<data name="fdType" xml:space="preserve">
<data name="fdType" xml:space="preserve">
<value>Type</value>
</data>
<data name="fdWrongFileTypeFeedback" xml:space="preserve">
<data name="fdWrongFileTypeFeedback" xml:space="preserve">
<value>Wrong file type</value>
<comment>When trying to open/save a file that does not match the provided filter (e.g. csv)</comment>
</data>
<data name="fdAnyFiles" xml:space="preserve">
<data name="fdAnyFiles" xml:space="preserve">
<value>Any Files</value>
<comment>Describes an AllowedType that matches anything</comment>
</data>
<data name="fdDeleteBody" xml:space="preserve">
<data name="fdDeleteBody" xml:space="preserve">
<value>Are you sure you want to delete '{0}'? This operation is permanent</value>
</data>
<data name="fdDeleteFailedTitle" xml:space="preserve">
<data name="fdDeleteFailedTitle" xml:space="preserve">
<value>Delete Failed</value>
</data>
<data name="fdDeleteTitle" xml:space="preserve">
<data name="fdDeleteTitle" xml:space="preserve">
<value>Delete {0}</value>
</data>
<data name="fdNewFailed" xml:space="preserve">
<data name="fdNewFailed" xml:space="preserve">
<value>New Failed</value>
</data>
<data name="fdNewTitle" xml:space="preserve">
<data name="fdNewTitle" xml:space="preserve">
<value>New Folder</value>
</data>
<data name="btnNo" xml:space="preserve">
<data name="btnNo" xml:space="preserve">
<value>_No</value>
</data>
<data name="fdRenameFailedTitle" xml:space="preserve">
<data name="fdRenameFailedTitle" xml:space="preserve">
<value>Rename Failed</value>
</data>
<data name="fdRenamePrompt" xml:space="preserve">
<data name="fdRenamePrompt" xml:space="preserve">
<value>Name:</value>
</data>
<data name="fdRenameTitle" xml:space="preserve">
<data name="fdRenameTitle" xml:space="preserve">
<value>Rename</value>
</data>
<data name="btnYes" xml:space="preserve">
<data name="btnYes" xml:space="preserve">
<value>_Yes</value>
</data>
<data name="fdExisting" xml:space="preserve">
<data name="fdExisting" xml:space="preserve">
<value>Existing</value>
</data>
<data name="btnOpen" xml:space="preserve">
<data name="btnOpen" xml:space="preserve">
<value>O_pen</value>
</data>
<data name="btnSave" xml:space="preserve">
<data name="btnSave" xml:space="preserve">
<value>_Save</value>
</data>
<data name="btnSaveAs" xml:space="preserve">
<data name="btnSaveAs" xml:space="preserve">
<value>Save _as</value>
</data>
<data name="btnOk" xml:space="preserve">
<data name="btnOk" xml:space="preserve">
<value>_OK</value>
</data>
<data name="btnCancel" xml:space="preserve">
<data name="btnCancel" xml:space="preserve">
<value>_Cancel</value>
</data>
<data name="fdCtxDelete" xml:space="preserve">
<data name="fdCtxDelete" xml:space="preserve">
<value>_Delete</value>
</data>
<data name="fdCtxHide" xml:space="preserve">
<data name="fdCtxHide" xml:space="preserve">
<value>_Hide {0}</value>
</data>
<data name="fdCtxNew" xml:space="preserve">
<data name="fdCtxNew" xml:space="preserve">
<value>_New</value>
</data>
<data name="fdCtxRename" xml:space="preserve">
<data name="fdCtxRename" xml:space="preserve">
<value>_Rename</value>
</data>
<data name="fdCtxSortAsc" xml:space="preserve">
<data name="fdCtxSortAsc" xml:space="preserve">
<value>_Sort {0} ASC</value>
</data>
<data name="fdCtxSortDesc" xml:space="preserve">
<data name="fdCtxSortDesc" xml:space="preserve">
<value>_Sort {0} DESC</value>
</data>
<data name="dpTitle" xml:space="preserve">
<data name="dpTitle" xml:space="preserve">
<value>Date Picker</value>
</data>
<data name="#F0F8FF" xml:space="preserve">
<data name="#F0F8FF" xml:space="preserve">
<value>AliceBlue</value>
</data>
<data name="#FAEBD7" xml:space="preserve">
<data name="#FAEBD7" xml:space="preserve">
<value>AntiqueWhite</value>
</data>
<data name="#7FFFD4" xml:space="preserve">
<data name="#7FFFD4" xml:space="preserve">
<value>Aquamarine</value>
</data>
<data name="#F0FFFF" xml:space="preserve">
<data name="#F0FFFF" xml:space="preserve">
<value>Azure</value>
</data>
<data name="#F5F5DC" xml:space="preserve">
<data name="#F5F5DC" xml:space="preserve">
<value>Beige</value>
</data>
<data name="#FFE4C4" xml:space="preserve">
<data name="#FFE4C4" xml:space="preserve">
<value>Bisque</value>
</data>
<data name="#000000" xml:space="preserve">
<data name="#000000" xml:space="preserve">
<value>Black</value>
</data>
<data name="#FFEBCD" xml:space="preserve">
<data name="#FFEBCD" xml:space="preserve">
<value>BlanchedAlmond</value>
</data>
<data name="#0000FF" xml:space="preserve">
<data name="#0000FF" xml:space="preserve">
<value>Blue</value>
</data>
<data name="#8A2BE2" xml:space="preserve">
<data name="#8A2BE2" xml:space="preserve">
<value>BlueViolet</value>
</data>
<data name="#A52A2A" xml:space="preserve">
<data name="#A52A2A" xml:space="preserve">
<value>Brown</value>
</data>
<data name="#DEB887" xml:space="preserve">
<data name="#DEB887" xml:space="preserve">
<value>BurlyWood</value>
</data>
<data name="#5F9EA0" xml:space="preserve">
<data name="#5F9EA0" xml:space="preserve">
<value>CadetBlue</value>
</data>
<data name="#7FFF00" xml:space="preserve">
<data name="#7FFF00" xml:space="preserve">
<value>Chartreuse</value>
</data>
<data name="#D2691E" xml:space="preserve">
<data name="#D2691E" xml:space="preserve">
<value>Chocolate</value>
</data>
<data name="#FF7F50" xml:space="preserve">
<data name="#FF7F50" xml:space="preserve">
<value>Coral</value>
</data>
<data name="#6495ED" xml:space="preserve">
<data name="#6495ED" xml:space="preserve">
<value>CornflowerBlue</value>
</data>
<data name="#FFF8DC" xml:space="preserve">
<data name="#FFF8DC" xml:space="preserve">
<value>Cornsilk</value>
</data>
<data name="#DC143C" xml:space="preserve">
<data name="#DC143C" xml:space="preserve">
<value>Crimson</value>
</data>
<data name="#00FFFF" xml:space="preserve">
<data name="#00FFFF" xml:space="preserve">
<value>Cyan</value>
</data>
<data name="#00008B" xml:space="preserve">
<data name="#00008B" xml:space="preserve">
<value>DarkBlue</value>
</data>
<data name="#008B8B" xml:space="preserve">
<data name="#008B8B" xml:space="preserve">
<value>DarkCyan</value>
</data>
<data name="#B8860B" xml:space="preserve">
<data name="#B8860B" xml:space="preserve">
<value>DarkGoldenRod</value>
</data>
<data name="#A9A9A9" xml:space="preserve">
<data name="#A9A9A9" xml:space="preserve">
<value>DarkGrey</value>
</data>
<data name="#006400" xml:space="preserve">
<data name="#006400" xml:space="preserve">
<value>DarkGreen</value>
</data>
<data name="#BDB76B" xml:space="preserve">
<data name="#BDB76B" xml:space="preserve">
<value>DarkKhaki</value>
</data>
<data name="#8B008B" xml:space="preserve">
<data name="#8B008B" xml:space="preserve">
<value>DarkMagenta</value>
</data>
<data name="#556B2F" xml:space="preserve">
<data name="#556B2F" xml:space="preserve">
<value>DarkOliveGreen</value>
</data>
<data name="#FF8C00" xml:space="preserve">
<data name="#FF8C00" xml:space="preserve">
<value>DarkOrange</value>
</data>
<data name="#9932CC" xml:space="preserve">
<data name="#9932CC" xml:space="preserve">
<value>DarkOrchid</value>
</data>
<data name="#8B0000" xml:space="preserve">
<data name="#8B0000" xml:space="preserve">
<value>DarkRed</value>
</data>
<data name="#E9967A" xml:space="preserve">
<data name="#E9967A" xml:space="preserve">
<value>DarkSalmon</value>
</data>
<data name="#8FBC8F" xml:space="preserve">
<data name="#8FBC8F" xml:space="preserve">
<value>DarkSeaGreen</value>
</data>
<data name="#483D8B" xml:space="preserve">
<data name="#483D8B" xml:space="preserve">
<value>DarkSlateBlue</value>
</data>
<data name="#2F4F4F" xml:space="preserve">
<data name="#2F4F4F" xml:space="preserve">
<value>DarkSlateGrey</value>
</data>
<data name="#00CED1" xml:space="preserve">
<data name="#00CED1" xml:space="preserve">
<value>DarkTurquoise</value>
</data>
<data name="#9400D3" xml:space="preserve">
<data name="#9400D3" xml:space="preserve">
<value>DarkViolet</value>
</data>
<data name="#FF1493" xml:space="preserve">
<data name="#FF1493" xml:space="preserve">
<value>DeepPink</value>
</data>
<data name="#00BFFF" xml:space="preserve">
<data name="#00BFFF" xml:space="preserve">
<value>DeepSkyBlue</value>
</data>
<data name="#696969" xml:space="preserve">
<data name="#696969" xml:space="preserve">
<value>DimGray</value>
</data>
<data name="#1E90FF" xml:space="preserve">
<data name="#1E90FF" xml:space="preserve">
<value>DodgerBlue</value>
</data>
<data name="#B22222" xml:space="preserve">
<data name="#B22222" xml:space="preserve">
<value>FireBrick</value>
</data>
<data name="#FFFAF0" xml:space="preserve">
<data name="#FFFAF0" xml:space="preserve">
<value>FloralWhite</value>
</data>
<data name="#228B22" xml:space="preserve">
<data name="#228B22" xml:space="preserve">
<value>ForestGreen</value>
</data>
<data name="#DCDCDC" xml:space="preserve">
<data name="#DCDCDC" xml:space="preserve">
<value>Gainsboro</value>
</data>
<data name="#F8F8FF" xml:space="preserve">
<data name="#F8F8FF" xml:space="preserve">
<value>GhostWhite</value>
</data>
<data name="#FFD700" xml:space="preserve">
<data name="#FFD700" xml:space="preserve">
<value>Gold</value>
</data>
<data name="#DAA520" xml:space="preserve">
<data name="#DAA520" xml:space="preserve">
<value>GoldenRod</value>
</data>
<data name="#808080" xml:space="preserve">
<data name="#808080" xml:space="preserve">
<value>Gray</value>
</data>
<data name="#008000" xml:space="preserve">
<data name="#008000" xml:space="preserve">
<value>Green</value>
</data>
<data name="#ADFF2F" xml:space="preserve">
<data name="#ADFF2F" xml:space="preserve">
<value>GreenYellow</value>
</data>
<data name="#F0FFF0" xml:space="preserve">
<data name="#F0FFF0" xml:space="preserve">
<value>HoneyDew</value>
</data>
<data name="#FF69B4" xml:space="preserve">
<data name="#FF69B4" xml:space="preserve">
<value>HotPink</value>
</data>
<data name="#CD5C5C" xml:space="preserve">
<data name="#CD5C5C" xml:space="preserve">
<value>IndianRed</value>
</data>
<data name="#4B0082" xml:space="preserve">
<data name="#4B0082" xml:space="preserve">
<value>Indigo</value>
</data>
<data name="#FFFFF0" xml:space="preserve">
<data name="#FFFFF0" xml:space="preserve">
<value>Ivory</value>
</data>
<data name="#F0E68C" xml:space="preserve">
<data name="#F0E68C" xml:space="preserve">
<value>Khaki</value>
</data>
<data name="#E6E6FA" xml:space="preserve">
<data name="#E6E6FA" xml:space="preserve">
<value>Lavender</value>
</data>
<data name="#FFF0F5" xml:space="preserve">
<data name="#FFF0F5" xml:space="preserve">
<value>LavenderBlush</value>
</data>
<data name="#7CFC00" xml:space="preserve">
<data name="#7CFC00" xml:space="preserve">
<value>LawnGreen</value>
</data>
<data name="#FFFACD" xml:space="preserve">
<data name="#FFFACD" xml:space="preserve">
<value>LemonChiffon</value>
</data>
<data name="#ADD8E6" xml:space="preserve">
<data name="#ADD8E6" xml:space="preserve">
<value>LightBlue</value>
</data>
<data name="#F08080" xml:space="preserve">
<data name="#F08080" xml:space="preserve">
<value>LightCoral</value>
</data>
<data name="#E0FFFF" xml:space="preserve">
<data name="#E0FFFF" xml:space="preserve">
<value>LightCyan</value>
</data>
<data name="#FAFAD2" xml:space="preserve">
<data name="#FAFAD2" xml:space="preserve">
<value>LightGoldenRodYellow</value>
</data>
<data name="#D3D3D3" xml:space="preserve">
<data name="#D3D3D3" xml:space="preserve">
<value>LightGray</value>
</data>
<data name="#90EE90" xml:space="preserve">
<data name="#90EE90" xml:space="preserve">
<value>LightGreen</value>
</data>
<data name="#FFB6C1" xml:space="preserve">
<data name="#FFB6C1" xml:space="preserve">
<value>LightPink</value>
</data>
<data name="#FFA07A" xml:space="preserve">
<data name="#FFA07A" xml:space="preserve">
<value>LightSalmon</value>
</data>
<data name="#20B2AA" xml:space="preserve">
<data name="#20B2AA" xml:space="preserve">
<value>LightSeaGreen</value>
</data>
<data name="#87CEFA" xml:space="preserve">
<data name="#87CEFA" xml:space="preserve">
<value>LightSkyBlue</value>
</data>
<data name="#778899" xml:space="preserve">
<data name="#778899" xml:space="preserve">
<value>LightSlateGrey</value>
</data>
<data name="#B0C4DE" xml:space="preserve">
<data name="#B0C4DE" xml:space="preserve">
<value>LightSteelBlue</value>
</data>
<data name="#FFFFE0" xml:space="preserve">
<data name="#FFFFE0" xml:space="preserve">
<value>LightYellow</value>
</data>
<data name="#00FF00" xml:space="preserve">
<data name="#00FF00" xml:space="preserve">
<value>Lime</value>
</data>
<data name="#32CD32" xml:space="preserve">
<data name="#32CD32" xml:space="preserve">
<value>LimeGreen</value>
</data>
<data name="#FAF0E6" xml:space="preserve">
<data name="#FAF0E6" xml:space="preserve">
<value>Linen</value>
</data>
<data name="#FF00FF" xml:space="preserve">
<data name="#FF00FF" xml:space="preserve">
<value>Magenta</value>
</data>
<data name="#800000" xml:space="preserve">
<data name="#800000" xml:space="preserve">
<value>Maroon</value>
</data>
<data name="#66CDAA" xml:space="preserve">
<data name="#66CDAA" xml:space="preserve">
<value>MediumAquaMarine</value>
</data>
<data name="#0000CD" xml:space="preserve">
<data name="#0000CD" xml:space="preserve">
<value>MediumBlue</value>
</data>
<data name="#BA55D3" xml:space="preserve">
<data name="#BA55D3" xml:space="preserve">
<value>MediumOrchid</value>
</data>
<data name="#9370DB" xml:space="preserve">
<data name="#9370DB" xml:space="preserve">
<value>MediumPurple</value>
</data>
<data name="#3CB371" xml:space="preserve">
<data name="#3CB371" xml:space="preserve">
<value>MediumSeaGreen</value>
</data>
<data name="#7B68EE" xml:space="preserve">
<data name="#7B68EE" xml:space="preserve">
<value>MediumSlateBlue</value>
</data>
<data name="#00FA9A" xml:space="preserve">
<data name="#00FA9A" xml:space="preserve">
<value>MediumSpringGreen</value>
</data>
<data name="#48D1CC" xml:space="preserve">
<data name="#48D1CC" xml:space="preserve">
<value>MediumTurquoise</value>
</data>
<data name="#C71585" xml:space="preserve">
<data name="#C71585" xml:space="preserve">
<value>MediumVioletRed</value>
</data>
<data name="#191970" xml:space="preserve">
<data name="#191970" xml:space="preserve">
<value>MidnightBlue</value>
</data>
<data name="#F5FFFA" xml:space="preserve">
<data name="#F5FFFA" xml:space="preserve">
<value>MintCream</value>
</data>
<data name="#FFE4E1" xml:space="preserve">
<data name="#FFE4E1" xml:space="preserve">
<value>MistyRose</value>
</data>
<data name="#FFE4B5" xml:space="preserve">
<data name="#FFE4B5" xml:space="preserve">
<value>Moccasin</value>
</data>
<data name="#FFDEAD" xml:space="preserve">
<data name="#FFDEAD" xml:space="preserve">
<value>NavajoWhite</value>
</data>
<data name="#000080" xml:space="preserve">
<data name="#000080" xml:space="preserve">
<value>Navy</value>
</data>
<data name="#FDF5E6" xml:space="preserve">
<data name="#FDF5E6" xml:space="preserve">
<value>OldLace</value>
</data>
<data name="#808000" xml:space="preserve">
<data name="#808000" xml:space="preserve">
<value>Olive</value>
</data>
<data name="#6B8E23" xml:space="preserve">
<data name="#6B8E23" xml:space="preserve">
<value>OliveDrab</value>
</data>
<data name="#FFA500" xml:space="preserve">
<data name="#FFA500" xml:space="preserve">
<value>Orange</value>
</data>
<data name="#FF4500" xml:space="preserve">
<data name="#FF4500" xml:space="preserve">
<value>OrangeRed</value>
</data>
<data name="#DA70D6" xml:space="preserve">
<data name="#DA70D6" xml:space="preserve">
<value>Orchid</value>
</data>
<data name="#EEE8AA" xml:space="preserve">
<data name="#EEE8AA" xml:space="preserve">
<value>PaleGoldenRod</value>
</data>
<data name="#98FB98" xml:space="preserve">
<data name="#98FB98" xml:space="preserve">
<value>PaleGreen</value>
</data>
<data name="#AFEEEE" xml:space="preserve">
<data name="#AFEEEE" xml:space="preserve">
<value>PaleTurquoise</value>
</data>
<data name="#DB7093" xml:space="preserve">
<data name="#DB7093" xml:space="preserve">
<value>PaleVioletRed</value>
</data>
<data name="#FFEFD5" xml:space="preserve">
<data name="#FFEFD5" xml:space="preserve">
<value>PapayaWhip</value>
</data>
<data name="#FFDAB9" xml:space="preserve">
<data name="#FFDAB9" xml:space="preserve">
<value>PeachPuff</value>
</data>
<data name="#CD853F" xml:space="preserve">
<data name="#CD853F" xml:space="preserve">
<value>Peru</value>
</data>
<data name="#FFC0CB" xml:space="preserve">
<data name="#FFC0CB" xml:space="preserve">
<value>Pink</value>
</data>
<data name="#DDA0DD" xml:space="preserve">
<data name="#DDA0DD" xml:space="preserve">
<value>Plum</value>
</data>
<data name="#B0E0E6" xml:space="preserve">
<data name="#B0E0E6" xml:space="preserve">
<value>PowderBlue</value>
</data>
<data name="#800080" xml:space="preserve">
<data name="#800080" xml:space="preserve">
<value>Purple</value>
</data>
<data name="#663399" xml:space="preserve">
<data name="#663399" xml:space="preserve">
<value>RebeccaPurple</value>
</data>
<data name="#FF0000" xml:space="preserve">
<data name="#FF0000" xml:space="preserve">
<value>Red</value>
</data>
<data name="#BC8F8F" xml:space="preserve">
<data name="#BC8F8F" xml:space="preserve">
<value>RosyBrown</value>
</data>
<data name="#4169E1" xml:space="preserve">
<data name="#4169E1" xml:space="preserve">
<value>RoyalBlue</value>
</data>
<data name="#8B4513" xml:space="preserve">
<data name="#8B4513" xml:space="preserve">
<value>SaddleBrown</value>
</data>
<data name="#FA8072" xml:space="preserve">
<data name="#FA8072" xml:space="preserve">
<value>Salmon</value>
</data>
<data name="#F4A460" xml:space="preserve">
<data name="#F4A460" xml:space="preserve">
<value>SandyBrown</value>
</data>
<data name="#2E8B57" xml:space="preserve">
<data name="#2E8B57" xml:space="preserve">
<value>SeaGreen</value>
</data>
<data name="#FFF5EE" xml:space="preserve">
<data name="#FFF5EE" xml:space="preserve">
<value>SeaShell</value>
</data>
<data name="#A0522D" xml:space="preserve">
<data name="#A0522D" xml:space="preserve">
<value>Sienna</value>
</data>
<data name="#C0C0C0" xml:space="preserve">
<data name="#C0C0C0" xml:space="preserve">
<value>Silver</value>
</data>
<data name="#87CEEB" xml:space="preserve">
<data name="#87CEEB" xml:space="preserve">
<value>SkyBlue</value>
</data>
<data name="#6A5ACD" xml:space="preserve">
<data name="#6A5ACD" xml:space="preserve">
<value>SlateBlue</value>
</data>
<data name="#708090" xml:space="preserve">
<data name="#708090" xml:space="preserve">
<value>SlateGray</value>
</data>
<data name="#FFFAFA" xml:space="preserve">
<data name="#FFFAFA" xml:space="preserve">
<value>Snow</value>
</data>
<data name="#00FF7F" xml:space="preserve">
<data name="#00FF7F" xml:space="preserve">
<value>SpringGreen</value>
</data>
<data name="#4682B4" xml:space="preserve">
<data name="#4682B4" xml:space="preserve">
<value>SteelBlue</value>
</data>
<data name="#D2B48C" xml:space="preserve">
<data name="#D2B48C" xml:space="preserve">
<value>Tan</value>
</data>
<data name="#008080" xml:space="preserve">
<data name="#008080" xml:space="preserve">
<value>Teal</value>
</data>
<data name="#D8BFD8" xml:space="preserve">
<data name="#D8BFD8" xml:space="preserve">
<value>Thistle</value>
</data>
<data name="#FF6347" xml:space="preserve">
<data name="#FF6347" xml:space="preserve">
<value>Tomato</value>
</data>
<data name="#40E0D0" xml:space="preserve">
<data name="#40E0D0" xml:space="preserve">
<value>Turquoise</value>
</data>
<data name="#EE82EE" xml:space="preserve">
<data name="#EE82EE" xml:space="preserve">
<value>Violet</value>
</data>
<data name="#F5DEB3" xml:space="preserve">
<data name="#F5DEB3" xml:space="preserve">
<value>Wheat</value>
</data>
<data name="#FFFFFF" xml:space="preserve">
<data name="#FFFFFF" xml:space="preserve">
<value>White</value>
</data>
<data name="#F5F5F5" xml:space="preserve">
<data name="#F5F5F5" xml:space="preserve">
<value>WhiteSmoke</value>
</data>
<data name="#FFFF00" xml:space="preserve">
<data name="#FFFF00" xml:space="preserve">
<value>Yellow</value>
</data>
<data name="#9ACD32" xml:space="preserve">
<data name="#9ACD32" xml:space="preserve">
<value>YellowGreen</value>
</data>
<data name="#3B78FF" xml:space="preserve">
<data name="#3B78FF" xml:space="preserve">
<value>BrightBlue</value>
</data>
<data name="#61D6D6" xml:space="preserve">
<data name="#61D6D6" xml:space="preserve">
<value>BrightCyan</value>
</data>
<data name="#E74856" xml:space="preserve">
<data name="#E74856" xml:space="preserve">
<value>BrightRed</value>
</data>
<data name="#16C60C" xml:space="preserve">
</data>
<data name="#16C60C" xml:space="preserve">
<value>BrightGreen</value>
</data>
<data name="#B4009E" xml:space="preserve">
</data>
<data name="#B4009E" xml:space="preserve">
<value>BrightMagenta</value>
</data>
<data name="#F9F1A5" xml:space="preserve">
</data>
<data name="#F9F1A5" xml:space="preserve">
<value>BrightYellow</value>
</data>
<data name="#767676" xml:space="preserve">
</data>
<data name="#767676" xml:space="preserve">
<value>DarkGray</value>
</data>
</data>
<data name="ctxColors" xml:space="preserve">
<value>Co_lors</value>
</data>
</root>

View File

@@ -153,9 +153,6 @@
<data name="fdOpen" xml:space="preserve">
<value>打开</value>
</data>
<data name="wzNext" xml:space="preserve">
<value>下一步 (_N)...</value>
</data>
<data name="fdSelectFolder" xml:space="preserve">
<value>选择文件夹 (_S)</value>
</data>
@@ -168,6 +165,9 @@
<data name="wzFinish" xml:space="preserve">
<value>结束 (_N)</value>
</data>
<data name="wzNext" xml:space="preserve">
<value>下一步 (_N)...</value>
</data>
<data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
<value>已存在相同名称的目录</value>
</data>
@@ -240,9 +240,6 @@
<data name="fdExisting" xml:space="preserve">
<value>已有</value>
</data>
<data name="btnOk" xml:space="preserve">
<value>确定 (_O)</value>
</data>
<data name="btnOpen" xml:space="preserve">
<value>打开 (_O)</value>
</data>
@@ -252,6 +249,9 @@
<data name="btnSaveAs" xml:space="preserve">
<value>另存为 (_S)</value>
</data>
<data name="btnOk" xml:space="preserve">
<value>确定 (_O)</value>
</data>
<data name="btnCancel" xml:space="preserve">
<value>取消 (_C)</value>
</data>
@@ -276,4 +276,7 @@
<data name="dpTitle" xml:space="preserve">
<value>日期选择器</value>
</data>
<data name="ctxColors" xml:space="preserve">
<value>旗帜 (_L)</value>
</data>
</root>

View File

@@ -464,7 +464,7 @@ public class TextField : View
/// Indicates whatever the text was changed or not. <see langword="true"/> if the text was changed
/// <see langword="false"/> otherwise.
/// </summary>
public bool IsDirty => _historyText.IsDirty (Text);
public bool IsDirty => _historyText.IsDirty ([Cell.StringToCells (Text)]);
/// <summary>If set to true its not allow any changes in the text.</summary>
public bool ReadOnly { get; set; }
@@ -594,7 +594,7 @@ public class TextField : View
}
/// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
public void ClearHistoryChanges () { _historyText.Clear (Text); }
public void ClearHistoryChanges () { _historyText.Clear ([Cell.StringToCells (Text)]); }
/// <summary>Copy the selected text to the clipboard.</summary>
public virtual void Copy ()

View File

@@ -180,7 +180,7 @@ internal class TextModel
{
if (_lines.Count > 0 && pos < _lines.Count)
{
_lines [pos] = new (runes);
_lines [pos] = [..runes];
}
else if (_lines.Count == 0 || (_lines.Count > 0 && pos >= _lines.Count))
{
@@ -1125,12 +1125,13 @@ internal partial class HistoryText
Original,
Replaced,
Removed,
Added
Added,
Attribute
}
private readonly List<HistoryTextItemEventArgs> _historyTextItems = new ();
private readonly List<HistoryTextItemEventArgs> _historyTextItems = [];
private int _idxHistoryText = -1;
private string? _originalText;
private List<List<Cell>> _originalCellsList = [];
public bool HasHistoryChanges => _idxHistoryText > -1;
public bool IsFromHistory { get; private set; }
@@ -1165,15 +1166,51 @@ internal partial class HistoryText
public event EventHandler<HistoryTextItemEventArgs>? ChangeText;
public void Clear (string text)
public void Clear (List<List<Cell>> cellsList)
{
_historyTextItems.Clear ();
_idxHistoryText = -1;
_originalText = text;
_originalCellsList.Clear ();
foreach (List<Cell> cells in cellsList)
{
_originalCellsList.Add ([..cells]);
}
OnChangeText (null);
}
public bool IsDirty (string text) { return _originalText != text; }
public bool IsDirty (List<List<Cell>> cellsList)
{
if (cellsList.Count != _originalCellsList.Count)
{
return true;
}
for (var r = 0; r < cellsList.Count; r++)
{
List<Cell> cells = cellsList [r];
List<Cell> originalCells = _originalCellsList [r];
if (cells.Count != originalCells.Count)
{
return true;
}
for (var c = 0; c < cells.Count; c++)
{
Cell cell = cells [c];
Cell originalCell = originalCells [c];
if (!cell.Equals (originalCell))
{
return true;
}
}
}
return false;
}
public void Redo ()
{
@@ -1227,7 +1264,8 @@ internal partial class HistoryText
if (_idxHistoryText - 1 > -1
&& (_historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Added
|| _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Removed
|| (historyTextItem.LineStatus == LineStatus.Replaced && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Original)))
|| (historyTextItem.LineStatus == LineStatus.Replaced && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Original)
|| (historyTextItem.LineStatus == LineStatus.Attribute && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Original)))
{
_idxHistoryText--;
@@ -1858,7 +1896,7 @@ public class TextView : View
CursorVisibility = CursorVisibility.Default;
Used = true;
// By default, disable hotkeys (in case someome sets Title)
// By default, disable hotkeys (in case someone sets Title)
HotKeySpecifier = new ('\xffff');
_model.LinesLoaded += Model_LinesLoaded!;
@@ -2264,6 +2302,15 @@ public class TextView : View
}
);
AddCommand (
Command.Open,
() =>
{
PromptForColors ();
return true;
});
// Default keybindings for this view
KeyBindings.Add (Key.PageDown, Command.PageDown);
KeyBindings.Add (Key.V.WithCtrl, Command.PageDown);
@@ -2357,6 +2404,8 @@ public class TextView : View
KeyBindings.Add (Key.G.WithCtrl, Command.DeleteAll);
KeyBindings.Add (Key.D.WithCtrl.WithShift, Command.DeleteAll);
KeyBindings.Add (Key.L.WithCtrl, Command.Open);
_currentCulture = Thread.CurrentThread.CurrentUICulture;
ContextMenu = new ();
@@ -2495,8 +2544,8 @@ public class TextView : View
/// </summary>
public bool IsDirty
{
get => _historyText.IsDirty (Text);
set => _historyText.Clear (Text);
get => _historyText.IsDirty (_model.GetAllLines ());
set => _historyText.Clear (_model.GetAllLines ());
}
/// <summary>Gets or sets the left column.</summary>
@@ -2585,15 +2634,21 @@ public class TextView : View
/// <summary>Length of the selected text.</summary>
public int SelectedLength => GetSelectedLength ();
private List<List<Cell>> _selectedCellsList = [];
/// <summary>
/// Gets the selected text as
/// <see>
/// <cref>List{List{Cell}}</cref>
/// </see>
/// </summary>
public List<List<Cell>> SelectedCellsList => _selectedCellsList;
public List<List<Cell>> SelectedCellsList
{
get
{
GetRegion (out List<List<Cell>> selectedCellsList);
return selectedCellsList;
}
}
/// <summary>The selected text.</summary>
public string SelectedText
@@ -2689,7 +2744,7 @@ public class TextView : View
OnTextChanged ();
SetNeedsDisplay ();
_historyText.Clear (Text);
_historyText.Clear (_model.GetAllLines ());
}
}
@@ -2741,7 +2796,7 @@ public class TextView : View
/// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
public void ClearHistoryChanges () { _historyText?.Clear (Text); }
public void ClearHistoryChanges () { _historyText?.Clear (_model.GetAllLines ()); }
/// <summary>Closes the contents of the stream into the <see cref="TextView"/>.</summary>
/// <returns><c>true</c>, if stream was closed, <c>false</c> otherwise.</returns>
@@ -2763,7 +2818,100 @@ public class TextView : View
/// </remarks>
public event EventHandler<ContentsChangedEventArgs>? ContentsChanged;
private string _copiedText;
internal void ApplyCellsAttribute (Attribute attribute)
{
if (!ReadOnly && SelectedLength > 0)
{
int startRow = Math.Min (SelectionStartRow, CurrentRow);
int endRow = Math.Max (CurrentRow, SelectionStartRow);
int startCol = SelectionStartRow <= CurrentRow ? SelectionStartColumn : CurrentColumn;
int endCol = CurrentRow >= SelectionStartRow ? CurrentColumn : SelectionStartColumn;
List<List<Cell>> selectedCellsOriginal = [];
List<List<Cell>> selectedCellsChanged = [];
for (int r = startRow; r <= endRow; r++)
{
List<Cell> line = GetLine (r);
selectedCellsOriginal.Add ([.. line]);
for (int c = r == startRow ? startCol : 0;
c < (r == endRow ? endCol : line.Count);
c++)
{
Cell cell = line [c]; // Copy value to a new variable
cell.Attribute = attribute; // Modify the copy
line [c] = cell; // Assign the modified copy back
}
selectedCellsChanged.Add ([..GetLine (r)]);
}
GetSelectedRegion ();
Selecting = false;
_historyText.Add (
[.. selectedCellsOriginal],
new (startCol, startRow)
);
_historyText.Add (
[.. selectedCellsChanged],
new (startCol, startRow),
HistoryText.LineStatus.Attribute
);
}
}
private Attribute? GetSelectedCellAttribute ()
{
List<Cell> line;
if (SelectedLength > 0)
{
line = GetLine (SelectionStartRow);
if (line [Math.Min (SelectionStartColumn, line.Count - 1)].Attribute is { } attributeSel)
{
return new (attributeSel);
}
return new (ColorScheme!.Focus);
}
line = GetCurrentLine ();
if (line [Math.Min (CurrentColumn, line.Count - 1)].Attribute is { } attribute)
{
return new (attribute);
}
return new (ColorScheme!.Focus);
}
/// <summary>
/// Open a dialog to set the foreground and background colors.
/// </summary>
public void PromptForColors ()
{
if (!Colors.PromptForColors (
"Colors",
GetSelectedCellAttribute (),
out Attribute newAttribute
))
{
return;
}
var attribute = new Attribute (
newAttribute.Foreground,
newAttribute.Background
);
ApplyCellsAttribute (attribute);
}
private string? _copiedText;
private List<List<Cell>> _copiedCellsList = [];
/// <summary>Copy the selected text to the clipboard contents.</summary>
@@ -3070,7 +3218,7 @@ public class TextView : View
{
SetWrapModel ();
res = _model.LoadFile (path);
_historyText.Clear (Text);
_historyText.Clear (_model.GetAllLines ());
ResetPosition ();
}
finally
@@ -3092,7 +3240,7 @@ public class TextView : View
{
SetWrapModel ();
_model.LoadStream (stream);
_historyText.Clear (Text);
_historyText.Clear (_model.GetAllLines ());
ResetPosition ();
SetNeedsDisplay ();
UpdateWrapModel ();
@@ -3104,7 +3252,7 @@ public class TextView : View
{
SetWrapModel ();
_model.LoadCells (cells, ColorScheme?.Focus);
_historyText.Clear (Text);
_historyText.Clear (_model.GetAllLines ());
ResetPosition ();
SetNeedsDisplay ();
UpdateWrapModel ();
@@ -3118,7 +3266,7 @@ public class TextView : View
SetWrapModel ();
InheritsPreviousAttribute = true;
_model.LoadListCells (cellsList, ColorScheme?.Focus);
_historyText.Clear (Text);
_historyText.Clear (_model.GetAllLines ());
ResetPosition ();
SetNeedsDisplay ();
UpdateWrapModel ();
@@ -4069,6 +4217,14 @@ public class TextView : View
null,
null,
(KeyCode)KeyBindings.GetKeyFromCommands (Command.Redo)
),
new (
Strings.ctxColors,
"",
() => PromptForColors (),
null,
null,
(KeyCode)KeyBindings.GetKeyFromCommands (Command.Open)
)
}
);
@@ -4460,7 +4616,7 @@ public class TextView : View
// Returns a string with the text in the selected
// region.
//
private string GetRegion (
internal string GetRegion (
out List<List<Cell>> cellsList,
int? sRow = null,
int? sCol = null,
@@ -4536,7 +4692,7 @@ public class TextView : View
OnUnwrappedCursorPosition (cRow, cCol);
return GetRegion (out _selectedCellsList, sRow: startRow, sCol: startCol, cRow: cRow, cCol: cCol, model: model);
return GetRegion (out _, sRow: startRow, sCol: startCol, cRow: cRow, cCol: cCol, model: model);
}
private (int Row, int Col) GetUnwrappedPosition (int line, int col)
@@ -4588,12 +4744,12 @@ public class TextView : View
for (var i = 0; i < obj.Lines.Count; i++)
{
if (i == 0)
if (i == 0 || obj.LineStatus == HistoryText.LineStatus.Original || obj.LineStatus == HistoryText.LineStatus.Attribute)
{
_model.ReplaceLine (startLine, obj.Lines [i]);
}
else if ((obj.IsUndoing && obj.LineStatus == HistoryText.LineStatus.Removed)
|| (!obj.IsUndoing && obj.LineStatus == HistoryText.LineStatus.Added))
else if (obj is { IsUndoing: true, LineStatus: HistoryText.LineStatus.Removed }
or { IsUndoing: false, LineStatus: HistoryText.LineStatus.Added })
{
_model.AddLine (startLine, obj.Lines [i]);
}
@@ -4671,7 +4827,7 @@ public class TextView : View
List<Cell> line = GetCurrentLine ();
_historyText.Add (new () { new (line) }, CursorPosition);
_historyText.Add ([new (line)], CursorPosition);
// Optimize single line
if (lines.Count == 1)
@@ -4680,7 +4836,7 @@ public class TextView : View
CurrentColumn += lines [0].Count;
_historyText.Add (
new () { new (line) },
[new (line)],
CursorPosition,
HistoryText.LineStatus.Replaced
);
@@ -4709,7 +4865,7 @@ public class TextView : View
}
List<Cell>? rest = null;
var lastp = 0;
var lastPosition = 0;
if (_model.Count > 0 && line.Count > 0 && !_copyWithoutSelection)
{
@@ -4724,19 +4880,19 @@ public class TextView : View
//model.AddLine (currentRow, lines [0]);
List<List<Cell>> addedLines = new () { new (line) };
List<List<Cell>> addedLines = [new (line)];
for (var i = 1; i < lines.Count; i++)
{
_model.AddLine (CurrentRow + i, lines [i]);
addedLines.Add (new (lines [i]));
addedLines.Add ([..lines [i]]);
}
if (rest is { })
{
List<Cell> last = _model.GetLine (CurrentRow + lines.Count - 1);
lastp = last.Count;
lastPosition = last.Count;
last.InsertRange (last.Count, rest);
addedLines.Last ().InsertRange (addedLines.Last ().Count, rest);
@@ -4746,11 +4902,11 @@ public class TextView : View
// Now adjust column and row positions
CurrentRow += lines.Count - 1;
CurrentColumn = rest is { } ? lastp : lines [lines.Count - 1].Count;
CurrentColumn = rest is { } ? lastPosition : lines [^1].Count;
Adjust ();
_historyText.Add (
new () { new (line) },
[new (line)],
CursorPosition,
HistoryText.LineStatus.Replaced
);
@@ -4769,7 +4925,7 @@ public class TextView : View
SetWrapModel ();
_historyText.Add (new () { new (GetCurrentLine ()) }, CursorPosition);
_historyText.Add ([new (GetCurrentLine ())], CursorPosition);
if (Selecting)
{
@@ -4807,7 +4963,7 @@ public class TextView : View
}
_historyText.Add (
new () { new (GetCurrentLine ()) },
[new (GetCurrentLine ())],
CursorPosition,
HistoryText.LineStatus.Replaced
);

View File

@@ -206,23 +206,11 @@ public class Editor : Scenario
new MenuItem (
"Colors",
"",
() =>
{
if (!PromptForColor (
"Colors",
GetSelectedCellAttribute (),
out Attribute newAttribute
))
{
return;
}
var attribute = new Attribute (newAttribute.Foreground,
newAttribute.Background
);
ApplyCellAttribute (attribute);
})
() => _textView.PromptForColors (),
null,
null,
KeyCode.CtrlMask | KeyCode.L
)
}
),
new (
@@ -337,165 +325,6 @@ public class Editor : Scenario
}
private void ApplyCellAttribute (Attribute attribute)
{
if (!_textView.ReadOnly && _textView.SelectedLength > 0)
{
var startRow = Math.Min (_textView.SelectionStartRow, _textView.CurrentRow);
var endRow = Math.Max (_textView.CurrentRow, _textView.SelectionStartRow);
var startCol = _textView.SelectionStartRow <= _textView.CurrentRow ? _textView.SelectionStartColumn : _textView.CurrentColumn;
var endCol = _textView.CurrentRow >= _textView.SelectionStartRow ? _textView.CurrentColumn : _textView.SelectionStartColumn;
for (int r = startRow; r <= endRow; r++)
{
List<Cell> line = _textView.GetLine (r);
for (int c = r == startRow ? startCol : 0;
c < (r == endRow ? endCol : line.Count);
c++)
{
Cell cell = line [c]; // Copy value to a new variable
cell.Attribute = attribute; // Modify the copy
line [c] = cell; // Assign the modified copy back
}
}
}
}
private Attribute? GetSelectedCellAttribute ()
{
List<Cell> line;
if (_textView.SelectedLength > 0)
{
line = _textView.GetLine (_textView.SelectionStartRow);
if (line [Math.Min (_textView.SelectionStartColumn, line.Count - 1)].Attribute is { } attributeSel)
{
return new (attributeSel);
}
return new (_textView.ColorScheme!.Focus);
}
line = _textView.GetCurrentLine ();
if (line [Math.Min (_textView.CurrentColumn, line.Count - 1)].Attribute is { } attribute)
{
return new (attribute);
}
return new (_textView.ColorScheme!.Focus);
}
public static bool PromptForColor (string title, Attribute? current, out Attribute newAttribute)
{
var accept = false;
var d = new Dialog
{
Title = title,
Width = Application.Force16Colors ? 37 : Dim.Auto (DimAutoStyle.Auto, Dim.Percent (80), Dim.Percent (90)),
Height = 20
};
var btnOk = new Button
{
X = Pos.Center () - 5,
Y = Application.Force16Colors ? 6 : 4,
Text = "Ok",
Width = Dim.Auto (),
IsDefault = true
};
btnOk.Accept += (s, e) =>
{
accept = true;
e.Handled = true;
Application.RequestStop ();
};
var btnCancel = new Button
{
X = Pos.Center () + 5,
Y = 4,
Text = "Cancel",
Width = Dim.Auto ()
};
btnCancel.Accept += (s, e) =>
{
e.Handled = true;
Application.RequestStop ();
};
d.Add (btnOk);
d.Add (btnCancel);
d.AddButton (btnOk);
d.AddButton (btnCancel);
View cpForeground;
if (Application.Force16Colors)
{
cpForeground = new ColorPicker16
{
SelectedColor = current!.Value.Foreground.GetClosestNamedColor16 (),
Width = Dim.Fill (),
BorderStyle = LineStyle.Single,
Title = "Foreground"
};
}
else
{
cpForeground = new ColorPicker
{
SelectedColor = current!.Value.Foreground,
Width = Dim.Fill (),
Style = new () { ShowColorName = true, ShowTextFields = true },
BorderStyle = LineStyle.Single,
Title = "Foreground"
};
((ColorPicker)cpForeground).ApplyStyleChanges ();
}
View cpBackground;
if (Application.Force16Colors)
{
cpBackground = new ColorPicker16
{
SelectedColor = current!.Value.Background.GetClosestNamedColor16 (),
Y = Pos.Bottom (cpForeground) + 1,
Width = Dim.Fill (),
BorderStyle = LineStyle.Single,
Title = "Background"
};
}
else
{
cpBackground = new ColorPicker
{
SelectedColor = current!.Value.Background,
Width = Dim.Fill (),
Y = Pos.Bottom (cpForeground) + 1,
Style = new () { ShowColorName = true, ShowTextFields = true },
BorderStyle = LineStyle.Single,
Title = "Background"
};
((ColorPicker)cpBackground).ApplyStyleChanges ();
}
d.Add (cpForeground, cpBackground);
Application.Run (d);
d.Dispose ();
var newForeColor = Application.Force16Colors ? ((ColorPicker16)cpForeground).SelectedColor : ((ColorPicker)cpForeground).SelectedColor;
var newBackColor = Application.Force16Colors ? ((ColorPicker16)cpBackground).SelectedColor : ((ColorPicker)cpBackground).SelectedColor;
newAttribute = new (newForeColor, newBackColor);
return accept;
}
private bool CanCloseFile ()
{
if (_textView.Text == Encoding.Unicode.GetString (_originalText))

View File

@@ -4713,6 +4713,86 @@ This is the second line.
Assert.Equal (new Point (0, 1), tv.CursorPosition);
}
[Fact]
public void HistoryText_Undo_Redo_ApplyCellsAttribute ()
{
var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
var tv = new TextView { Text = text };
tv.SelectionStartColumn = 12;
tv.CursorPosition = new Point (18, 1);
Assert.Equal (31, tv.SelectedLength);
Assert.Equal ($"first line.{Environment.NewLine}This is the second", tv.SelectedText);
Assert.Equal ($"first line.{Environment.NewLine}This is the second", Cell.ToString (tv.SelectedCellsList));
Assert.Equal (new Point (18, 1), tv.CursorPosition);
Assert.False (tv.IsDirty);
AssertNullAttribute ();
tv.ApplyCellsAttribute (new (Color.Red, Color.Green));
AssertRedGreenAttribute ();
Assert.Equal (0, tv.SelectedLength);
Assert.Equal ("", tv.SelectedText);
Assert.Equal ($"first line.{Environment.NewLine}This is the second", Cell.ToString (tv.SelectedCellsList));
Assert.Equal (new Point (18, 1), tv.CursorPosition);
Assert.True (tv.IsDirty);
// Undo
Assert.True (tv.NewKeyDownEvent (Key.Z.WithCtrl));
AssertNullAttribute ();
Assert.Equal (12, tv.SelectionStartColumn);
Assert.Equal (0, tv.SelectionStartRow);
Assert.Equal (0, tv.SelectedLength);
Assert.Equal ("", tv.SelectedText);
Assert.Empty (tv.SelectedCellsList);
Assert.Equal (new Point (12, 0), tv.CursorPosition);
Assert.False (tv.IsDirty);
// Redo
Assert.True (tv.NewKeyDownEvent (Key.R.WithCtrl));
AssertRedGreenAttribute ();
Assert.Equal (12, tv.SelectionStartColumn);
Assert.Equal (0, tv.SelectionStartRow);
Assert.Equal (0, tv.SelectedLength);
Assert.Equal ("", tv.SelectedText);
Assert.Empty (tv.SelectedCellsList);
Assert.Equal (new Point (12, 0), tv.CursorPosition);
Assert.True (tv.IsDirty);
void AssertNullAttribute ()
{
tv.GetRegion (out List<List<Cell>> region, 0, 12, 1, 18);
foreach (List<Cell> cells in region)
{
foreach (Cell cell in cells)
{
Assert.Null (cell.Attribute);
}
}
}
void AssertRedGreenAttribute ()
{
tv.GetRegion (out List<List<Cell>> region, 0, 12, 1, 18);
foreach (List<Cell> cells in region)
{
foreach (Cell cell in cells)
{
Assert.Equal ("[Red,Green]", cell.Attribute.ToString ());
}
}
}
}
[Fact]
public void Internal_Tests ()
{