diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 514957577..db34f23bb 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,42 +1,42 @@
-name: Publish Terminal.Gui v2
+name: Publish Terminal.Gui
+
on:
push:
+ branches: [ main, develop, v2_release, v2_develop ]
tags:
- - v2.0.0-alpha.*
+ - v*
+ paths-ignore:
+ - '**.md'
jobs:
publish:
- name: Build and Publish v2 to Nuget.org
+ name: Build and Publish to Nuget.org
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
- fetch-depth: 0 #fetch-depth is needed for GitVersion
+ fetch-depth: 0 # fetch-depth is needed for GitVersion
- - name: Install and calculate the new version with GitVersion
+ - name: Install GitVersion
uses: gittools/actions/gitversion/setup@v0
with:
- versionSpec: '6.x'
+ versionSpec: '5.x'
includePrerelease: true
- name: Determine Version
uses: gittools/actions/gitversion/execute@v0
with:
- useConfigFile: true
+ useConfigFile: true
+ #additionalArguments: /b develop
id: gitversion # step id used as reference for output values
- - name: Display GitVersion outputs
- run: |
- echo "Version: ${{ steps.gitversion.outputs.SemVer }}"
- echo "CommitsSinceVersionSource: ${{ steps.gitversion.outputs.CommitsSinceVersionSource }}"
-
- name: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0
dotnet-quality: 'ga'
-
+
- name: Install dependencies
run: dotnet restore
@@ -48,34 +48,27 @@ jobs:
- name: Pack
run: dotnet pack -c Release --include-symbols -p:Version='${{ steps.gitversion.outputs.SemVer }}'
- #- name: Test to generate Code Coverage Report
- # run: |
- # sed -i 's/"stopOnFail": false/"stopOnFail": true/g' UnitTests/xunit.runner.json
- # dotnet test --verbosity normal --collect:"XPlat Code Coverage" --settings UnitTests/coverlet.runsettings
- # mv -v UnitTests/TestResults/*/*.* UnitTests/TestResults/
+ # - name: Test to generate Code Coverage Report
+ # run: |
+ # sed -i 's/"stopOnFail": false/"stopOnFail": true/g' UnitTests/xunit.runner.json
+ # dotnet test --verbosity normal --collect:"XPlat Code Coverage" --settings UnitTests/coverlet.runsettings
+ # mv -v UnitTests/TestResults/*/*.* UnitTests/TestResults/
- #- name: Create Test Coverage Badge
- # uses: simon-k/dotnet-code-coverage-badge@v1.0.0
- # id: create_coverage_badge
- # with:
- # label: Unit Test Coverage
- # color: brightgreen
- # path: UnitTests/TestResults/coverage.opencover.xml
- # gist-filename: code-coverage.json
- # # https://gist.github.com/migueldeicaza/90ef67a684cb71db1817921a970f8d27
- # gist-id: 90ef67a684cb71db1817921a970f8d27
- # gist-auth-token: ${{ secrets.GIST_AUTH_TOKEN }}
-
- #- name: Print Code Coverage
- # run: |
- # echo "Code coverage percentage: ${{steps.create_coverage_badge.outputs.percentage}}%"
- # echo "Badge data: ${{steps.create_coverage_badge.outputs.badge}}"
+ # - name: Create Test Coverage Badge
+ # uses: simon-k/dotnet-code-coverage-badge@v1.0.0
+ # id: create_coverage_badge
+ # with:
+ # label: Unit Test Coverage
+ # color: brightgreen
+ # path: UnitTests/TestResults/coverage.opencover.xml
+ # gist-filename: code-coverage.json
+ # gist-id: 90ef67a684cb71db1817921a970f8d27
+ # gist-auth-token: ${{ secrets.GIST_AUTH_TOKEN }}
+ # - name: Print Code Coverage
+ # run: |
+ # echo "Code coverage percentage: ${{steps.create_coverage_badge.outputs.percentage}}%"
+ # echo "Badge data: ${{steps.create_coverage_badge.outputs.badge}}"
+
- name: Publish to NuGet.org
- run: dotnet nuget push Terminal.Gui/bin/Release/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
-
- - name: Unlist from NuGet.org if it's an alpha
- run: dotnet nuget delete --non-interactive Terminal.Gui ${{ steps.gitversion.outputs.SemVer }} --api-key ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
- if: contains(steps.gitversion.outputs.SemVer, 'alpha')
-
-
+ run: dotnet nuget push Terminal.Gui/bin/Release/Terminal.Gui.${{ steps.gitversion.outputs.SemVer }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }}
diff --git a/GitVersion.yml b/GitVersion.yml
index f77b10ac2..d5f370a83 100644
--- a/GitVersion.yml
+++ b/GitVersion.yml
@@ -1,21 +1,14 @@
mode: ContinuousDeployment
tag-prefix: '[vV]'
-continuous-delivery-fallback-tag: 'pre'
+continuous-delivery-fallback-tag: pre
branches:
- # v1_develop:
- # mode: ContinuousDeployment
- # tag: pre
- # regex: ^v1_develop?[/-]
- # is-release-branch: false
- # source-branches:
- # - v1
- # v1:
- # tag: rc
- # increment: Patch
- # regex: ^v2?[/-]
- # is-release-branch: false
- # source-branches: []
- # is-mainline: true
+ develop:
+ mode: ContinuousDeployment
+ tag: pre
+ regex: develop
+ source-branches:
+ - main
+ pre-release-weight: 100
v2_develop:
mode: ContinuousDeployment
@@ -23,28 +16,76 @@ branches:
regex: ^v2_develop?[/-]
is-release-branch: true
tracks-release-branches: true
- is-source-branch-for: ['v2']
+ #is-source-branch-for: ['v2']
source-branches: []
- v2:
- mode: ContinuousDeployment
- is-release-branch: false
- tag: alpha
- increment: Patch
- regex: ^v2?[/-]
- source-branches: ['v2_develop']
- # feature:
- # tag: useBranchName
- # regex: ^features?[/-]
- # source-branches:
- # - v1
- # - v1_develop
- # - v2
- # - v2_develop
-
+ main:
+ tag: rc
+ increment: Patch
+ source-branches:
+ - develop
+ - main
+ feature:
+ tag: useBranchName
+ regex: ^features?[/-]
+ source-branches:
+ - develop
+ - main
pull-request:
tag: PullRequest.{BranchName}
increment: Inherit
ignore:
sha: []
-merge-message-formats: {}
+
+
+# next-version: 2.0.0
+# mode: ContinuousDeployment
+# tag-prefix: '[vV]'
+# continuous-delivery-fallback-tag: 'pre'
+# branches:
+# # v1_develop:
+# # mode: ContinuousDeployment
+# # tag: pre
+# # regex: ^v1_develop?[/-]
+# # is-release-branch: false
+# # source-branches:
+# # - v1
+# # v1:
+# # tag: rc
+# # increment: Patch
+# # regex: ^v2?[/-]
+# # is-release-branch: false
+# # source-branches: []
+# # is-mainline: true
+
+# v2_develop:
+# mode: ContinuousDeployment
+# tag: pre
+# regex: ^v2_develop?[/-]
+# is-release-branch: true
+# tracks-release-branches: true
+# is-source-branch-for: ['v2']
+# source-branches: []
+# v2:
+# mode: ContinuousDeployment
+# is-release-branch: false
+# tag: alpha
+# increment: Patch
+# regex: ^v2?[/-]
+# source-branches: ['v2_develop']
+
+# # feature:
+# # tag: useBranchName
+# # regex: ^features?[/-]
+# # source-branches:
+# # - v1
+# # - v1_develop
+# # - v2
+# # - v2_develop
+
+# pull-request:
+# tag: PullRequest.{BranchName}
+# increment: Inherit
+# ignore:
+# sha: []
+# merge-message-formats: {}
diff --git a/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
index cbf26d6ef..37f4447e8 100644
--- a/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
@@ -360,7 +360,6 @@ public abstract class ConsoleDriver {
#region Color Handling
-
///
/// Gets whether the supports TrueColor output.
///
@@ -380,7 +379,6 @@ public abstract class ConsoleDriver {
get => _force16Colors || !SupportsTrueColor;
set {
_force16Colors = (value || !SupportsTrueColor);
- Refresh ();
}
}
@@ -533,7 +531,7 @@ public abstract class ConsoleDriver {
/// Ends the execution of the console driver.
///
public abstract void End ();
-
+
///
/// Returns the name of the driver and relevant library version information.
///
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index f1f0646dc..e84cc408f 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -777,21 +777,11 @@ internal class WindowsDriver : ConsoleDriver {
public WindowsConsole WinConsole { get; private set; }
- public override bool SupportsTrueColor => RunningUnitTests || (Environment.OSVersion.Version.Build >= 14931);
-
- public override bool Force16Colors {
- get => base.Force16Colors;
- set {
- base.Force16Colors = value;
- // BUGBUG: This is a hack until we fully support VirtualTerminalSequences
- if (WinConsole != null) {
- WinConsole = new WindowsConsole ();
- }
- Refresh ();
- }
- }
+ public override bool SupportsTrueColor => RunningUnitTests || (Environment.OSVersion.Version.Build >= 14931
+ && (_isWindowsTerminal || _parentProcessName == "devenv"));
readonly bool _isWindowsTerminal = false;
+ readonly string _parentProcessName = "WindowsTerminal";
public WindowsDriver ()
{
@@ -803,8 +793,52 @@ internal class WindowsDriver : ConsoleDriver {
Clipboard = new FakeDriver.FakeClipboard ();
}
- _isWindowsTerminal = Environment.GetEnvironmentVariable ("WT_SESSION") != null;
+ if (!RunningUnitTests) {
+ _parentProcessName = GetParentProcessName ();
+ _isWindowsTerminal = _parentProcessName == "WindowsTerminal";
+ if (!_isWindowsTerminal && _parentProcessName != "devenv") {
+ Force16Colors = true;
+ }
+ }
+ }
+ private static string GetParentProcessName ()
+ {
+#pragma warning disable CA1416 // Validate platform compatibility
+ var myId = Process.GetCurrentProcess ().Id;
+ var query = string.Format ($"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {myId}");
+ var search = new ManagementObjectSearcher ("root\\CIMV2", query);
+ var queryObj = search.Get ().OfType ().FirstOrDefault ();
+ if (queryObj == null) {
+ return null;
+ }
+ var parentId = (uint)queryObj ["ParentProcessId"];
+ var parent = Process.GetProcessById ((int)parentId);
+ var prevParent = parent;
+
+ // Check if the parent is from other parent
+ while (queryObj != null) {
+ query = string.Format ($"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {parentId}");
+ search = new ManagementObjectSearcher ("root\\CIMV2", query);
+ queryObj = search.Get ().OfType ().FirstOrDefault ();
+ if (queryObj == null) {
+ return parent.ProcessName;
+ }
+ parentId = (uint)queryObj ["ParentProcessId"];
+ try {
+ parent = Process.GetProcessById ((int)parentId);
+ if (string.Equals (parent.ProcessName, "explorer", StringComparison.InvariantCultureIgnoreCase)) {
+ return prevParent.ProcessName;
+ }
+ prevParent = parent;
+ } catch (ArgumentException) {
+
+ return prevParent.ProcessName;
+ }
+ }
+
+ return parent.ProcessName;
+#pragma warning restore CA1416 // Validate platform compatibility
}
public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler)
@@ -1454,13 +1488,13 @@ internal class WindowsDriver : ConsoleDriver {
if (RunningUnitTests) {
return;
}
-
+
try {
if (WinConsole != null) {
var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
Cols = winSize.Width;
Rows = winSize.Height;
- }
+ }
WindowsConsole.SmallRect.MakeEmpty (ref _damageRegion);
// Needed for Windows Terminal
@@ -1511,8 +1545,7 @@ internal class WindowsDriver : ConsoleDriver {
WinConsole?.ForceRefreshCursorVisibility ();
}
-
-
+
public override void UpdateScreen ()
{
var windowSize = WinConsole?.GetConsoleBufferWindow (out _) ?? new Size (Cols, Rows);
@@ -1709,9 +1742,9 @@ internal class WindowsDriver : ConsoleDriver {
WinConsole?.Cleanup ();
WinConsole = null;
- if (!RunningUnitTests && _isWindowsTerminal) {
+ if (!RunningUnitTests && (_isWindowsTerminal || _parentProcessName == "devenv")) {
// Disable alternative screen buffer.
- Console.Out.Write (EscSeqUtils.CSI_RestoreAltBufferWithBackscroll);
+ Console.Out.Write (EscSeqUtils.CSI_RestoreCursorAndActivateAltBufferWithBackscroll);
}
}
@@ -1797,8 +1830,8 @@ internal class WindowsMainLoop : IMainLoopDriver {
while (true) {
Task.Delay (500).Wait ();
_windowSize = _winConsole.GetConsoleBufferWindow (out _);
- if (_windowSize != Size.Empty && _windowSize.Width != _consoleDriver.Cols
- || _windowSize.Height != _consoleDriver.Rows) {
+ if (_windowSize != Size.Empty && (_windowSize.Width != _consoleDriver.Cols
+ || _windowSize.Height != _consoleDriver.Rows)) {
return;
}
}
diff --git a/Terminal.Gui/FileServices/DefaultFileOperations.cs b/Terminal.Gui/FileServices/DefaultFileOperations.cs
index b2512cea6..c626dfaec 100644
--- a/Terminal.Gui/FileServices/DefaultFileOperations.cs
+++ b/Terminal.Gui/FileServices/DefaultFileOperations.cs
@@ -24,7 +24,7 @@ namespace Terminal.Gui {
int result = MessageBox.Query (
string.Format (Strings.fdDeleteTitle, adjective),
string.Format (Strings.fdDeleteBody, adjective),
- Strings.fdYes, Strings.fdNo);
+ Strings.btnYes, Strings.btnNo);
try {
if (result == 0) {
@@ -37,7 +37,7 @@ namespace Terminal.Gui {
return true;
}
} catch (Exception ex) {
- MessageBox.ErrorQuery (Strings.fdDeleteFailedTitle, ex.Message, "Ok");
+ MessageBox.ErrorQuery (Strings.fdDeleteFailedTitle, ex.Message, Strings.btnOk);
}
return false;
@@ -47,14 +47,14 @@ namespace Terminal.Gui {
{
bool confirm = false;
- var btnOk = new Button ("Ok") {
+ var btnOk = new Button (Strings.btnOk) {
IsDefault = true,
};
btnOk.Clicked += (s, e) => {
confirm = true;
Application.RequestStop ();
};
- var btnCancel = new Button ("Cancel");
+ var btnCancel = new Button (Strings.btnCancel);
btnCancel.Clicked += (s, e) => {
confirm = false;
Application.RequestStop ();
diff --git a/Terminal.Gui/Resources/Strings.Designer.cs b/Terminal.Gui/Resources/Strings.Designer.cs
index 00d978a76..a71f357ce 100644
--- a/Terminal.Gui/Resources/Strings.Designer.cs
+++ b/Terminal.Gui/Resources/Strings.Designer.cs
@@ -60,6 +60,69 @@ namespace Terminal.Gui.Resources {
}
}
+ ///
+ /// Looks up a localized string similar to Cancel.
+ ///
+ internal static string btnCancel {
+ get {
+ return ResourceManager.GetString("btnCancel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to No.
+ ///
+ internal static string btnNo {
+ get {
+ return ResourceManager.GetString("btnNo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to OK.
+ ///
+ internal static string btnOk {
+ get {
+ return ResourceManager.GetString("btnOk", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Open.
+ ///
+ internal static string btnOpen {
+ get {
+ return ResourceManager.GetString("btnOpen", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Save.
+ ///
+ internal static string btnSave {
+ get {
+ return ResourceManager.GetString("btnSave", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Save as.
+ ///
+ internal static string btnSaveAs {
+ get {
+ return ResourceManager.GetString("btnSaveAs", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Yes.
+ ///
+ internal static string btnYes {
+ get {
+ return ResourceManager.GetString("btnYes", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to _Copy.
///
@@ -267,15 +330,6 @@ namespace Terminal.Gui.Resources {
}
}
- ///
- /// Looks up a localized string similar to No.
- ///
- internal static string fdNo {
- get {
- return ResourceManager.GetString("fdNo", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Open.
///
@@ -393,15 +447,6 @@ namespace Terminal.Gui.Resources {
}
}
- ///
- /// Looks up a localized string similar to Yes.
- ///
- internal static string fdYes {
- get {
- return ResourceManager.GetString("fdYes", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to _Back.
///
diff --git a/Terminal.Gui/Resources/Strings.fr-FR.resx b/Terminal.Gui/Resources/Strings.fr-FR.resx
index 28a48dc1d..e6dcfcaea 100644
--- a/Terminal.Gui/Resources/Strings.fr-FR.resx
+++ b/Terminal.Gui/Resources/Strings.fr-FR.resx
@@ -142,16 +142,16 @@
_Dossier
- _Ficher
+ Ficher
- _Enregistrer
+ Enregistrer
- E_nregistrer sous
+ Enregistrer sous
- _Ouvrir
+ Ouvrir
Sélection de _dossier
@@ -168,4 +168,13 @@
Prochai_n...
+
+ Enregistrer
+
+
+ E_nregistrer sous
+
+
+ Ouvrir
+
\ No newline at end of file
diff --git a/Terminal.Gui/Resources/Strings.ja-JP.resx b/Terminal.Gui/Resources/Strings.ja-JP.resx
index 68b15dda8..35d0e2bf8 100644
--- a/Terminal.Gui/Resources/Strings.ja-JP.resx
+++ b/Terminal.Gui/Resources/Strings.ja-JP.resx
@@ -118,25 +118,25 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- コピー (C)
+ コピー (_C)
- 切り取り (T)
+ 切り取り (_T)
- 全て削除 (D)
+ 全て削除 (_D)
- 貼り付け (P)
+ 貼り付け (_P)
- やり直し (R)
+ やり直し (_R)
- 全て選択 (S)
+ 全て選択 (_S)
- 元に戻す (U)
+ 元に戻す (_U)
ディレクトリ
@@ -154,18 +154,105 @@
開く
- フォルダーを選択
+ フォルダーを選択 (_S)
- 混在選択
+ 混在選択 (_S)
- 戻る
+ 戻る (_B)
- 終える
+ 終わる (_N)
- 次に
+ 次に (_N)...
+
+
+ 同じ名前のディレクトリはすでに存在しました
+
+
+ “{0}”を削除もよろしいですか?この操作は元に戻りません
+
+
+ タイプ
+
+
+ サイズ
+
+
+ パスを入力
+
+
+ ファイル名
+
+
+ 新規ディレクトリ
+
+
+ いいえ (_N)
+
+
+ はい (_Y)
+
+
+ 変更日時
+
+
+ すでに存在したファイルまたはディレクトリを選択してください
+
+
+ すでに存在したディレクトリを選択してください
+
+
+ すでに存在したファイルを選択してください
+
+
+ 名前:
+
+
+ {0} を削除
+
+
+ 新規失敗
+
+
+ 既存
+
+
+ 名前を変更
+
+
+ 変更失敗
+
+
+ 削除失敗
+
+
+ 同じ名前のファイルはすでに存在しました
+
+
+ 検索を入力
+
+
+ ファイルタイプが間違っでいます
+
+
+ 任意ファイル
+
+
+ キャンセル (_C)
+
+
+ OK (_O)
+
+
+ 開く (_O)
+
+
+ 保存 (_S)
+
+
+ 名前を付けて保存 (_S)
\ No newline at end of file
diff --git a/Terminal.Gui/Resources/Strings.pt-PT.resx b/Terminal.Gui/Resources/Strings.pt-PT.resx
index a8385c556..bfd60ce15 100644
--- a/Terminal.Gui/Resources/Strings.pt-PT.resx
+++ b/Terminal.Gui/Resources/Strings.pt-PT.resx
@@ -168,4 +168,13 @@
S_eguir
+
+ Guardar como
+
+
+ Guardar
+
+
+ Abrir
+
\ No newline at end of file
diff --git a/Terminal.Gui/Resources/Strings.resx b/Terminal.Gui/Resources/Strings.resx
index 873c6184d..887431f43 100644
--- a/Terminal.Gui/Resources/Strings.resx
+++ b/Terminal.Gui/Resources/Strings.resx
@@ -226,7 +226,7 @@
New Folder
-
+
No
@@ -238,10 +238,25 @@
Rename
-
+
Yes
Existing
+
+ Open
+
+
+ Save
+
+
+ Save as
+
+
+ OK
+
+
+ Cancel
+
\ No newline at end of file
diff --git a/Terminal.Gui/Resources/Strings.zh-Hans.resx b/Terminal.Gui/Resources/Strings.zh-Hans.resx
new file mode 100644
index 000000000..b0358523f
--- /dev/null
+++ b/Terminal.Gui/Resources/Strings.zh-Hans.resx
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 全选 (_S)
+
+
+ 清空 (_D)
+
+
+ 复制 (_C)
+
+
+ 剪切 (_T)
+
+
+ 粘贴 (_P)
+
+
+ 撤销 (_U)
+
+
+ 重做 (_R)
+
+
+ 目录
+
+
+ 文件
+
+
+ 保存
+
+
+ 另存为
+
+
+ 打开
+
+
+ 下一步 (_N)...
+
+
+ 选择文件夹 (_S)
+
+
+ 混合选择 (_S)
+
+
+ 返回 (_B)
+
+
+ 结束 (_N)
+
+
+ 已存在相同名称的目录
+
+
+ 必须选择已有的目录
+
+
+ 已存在相同名称的文件
+
+
+ 必须选择已有的文件
+
+
+ 文件名
+
+
+ 必须选择已有的文件或目录
+
+
+ 修改时间
+
+
+ 请输入路径
+
+
+ 输入以搜索
+
+
+ 大小
+
+
+ 类型
+
+
+ 文件类型有误
+
+
+ 任意文件
+
+
+ 您是否要删除“{0}”?此操作不可撤销
+
+
+ 删除失败
+
+
+ 删除 {0}
+
+
+ 新建失败
+
+
+ 新建文件夹
+
+
+ 否 (_N)
+
+
+ 重命名失败
+
+
+ 名称:
+
+
+ 重命名
+
+
+ 是 (_Y)
+
+
+ 已有
+
+
+ 确定 (_O)
+
+
+ 打开 (_O)
+
+
+ 保存 (_S)
+
+
+ 另存为 (_S)
+
+
+ 取消 (_C)
+
+
\ No newline at end of file
diff --git a/Terminal.Gui/Views/FileDialog.cs b/Terminal.Gui/Views/FileDialog.cs
index bf5b9adf2..e71fdf9c6 100644
--- a/Terminal.Gui/Views/FileDialog.cs
+++ b/Terminal.Gui/Views/FileDialog.cs
@@ -154,7 +154,7 @@ namespace Terminal.Gui {
this.NavigateIf (k, Key.CursorUp, this.tableView);
};
- this.btnCancel = new Button ("Cancel") {
+ this.btnCancel = new Button (Strings.btnCancel) {
Y = Pos.AnchorEnd (1),
X = Pos.Function (() =>
this.Bounds.Width
@@ -710,20 +710,32 @@ namespace Terminal.Gui {
this.tbPath.SelectAll ();
if (string.IsNullOrEmpty (Title)) {
- switch (OpenMode) {
- case OpenMode.File:
- this.Title = $"{Strings.fdOpen} {(MustExist ? Strings.fdExisting + " " : "")}{Strings.fdFile}";
- break;
- case OpenMode.Directory:
- this.Title = $"{Strings.fdOpen} {(MustExist ? Strings.fdExisting + " " : "")}{Strings.fdDirectory}";
- break;
- case OpenMode.Mixed:
- this.Title = $"{Strings.fdOpen} {(MustExist ? Strings.fdExisting : "")}";
- break;
- }
+ this.Title = GetDefaultTitle ();
}
this.LayoutSubviews ();
}
+ ///
+ /// Gets a default dialog title, when is not set or empty,
+ /// result of the function will be shown.
+ ///
+ protected virtual string GetDefaultTitle ()
+ {
+ List titleParts = new () {
+ Strings.fdOpen
+ };
+ if (MustExist) {
+ titleParts.Add (Strings.fdExisting);
+ }
+ switch (OpenMode) {
+ case OpenMode.File:
+ titleParts.Add (Strings.fdFile);
+ break;
+ case OpenMode.Directory:
+ titleParts.Add (Strings.fdDirectory);
+ break;
+ }
+ return string.Join (' ', titleParts);
+ }
private void AllowedTypeMenuClicked (int idx)
{
diff --git a/Terminal.Gui/Views/OpenDialog.cs b/Terminal.Gui/Views/OpenDialog.cs
index 4e16831fe..674a585ee 100644
--- a/Terminal.Gui/Views/OpenDialog.cs
+++ b/Terminal.Gui/Views/OpenDialog.cs
@@ -55,8 +55,7 @@ namespace Terminal.Gui {
/// To select more than one file, users can use the spacebar, or control-t.
///
///
- public class OpenDialog : FileDialog {
-
+ public class OpenDialog : FileDialog {
///
/// Initializes a new .
///
@@ -70,9 +69,9 @@ namespace Terminal.Gui {
/// The open mode.
public OpenDialog (string title, List allowedTypes = null, OpenMode openMode = OpenMode.File)
{
- this.OpenMode = openMode;
+ OpenMode = openMode;
Title = title;
- Style.OkButtonText = openMode == OpenMode.File ? Strings.fdOpen : openMode == OpenMode.Directory ? Strings.fdSelectFolder : Strings.fdSelectMixed;
+ Style.OkButtonText = openMode == OpenMode.File ? Strings.btnOpen : openMode == OpenMode.Directory ? Strings.fdSelectFolder : Strings.fdSelectMixed;
if (allowedTypes != null) {
AllowedTypes = allowedTypes;
diff --git a/Terminal.Gui/Views/SaveDialog.cs b/Terminal.Gui/Views/SaveDialog.cs
index b5d689311..e357e704f 100644
--- a/Terminal.Gui/Views/SaveDialog.cs
+++ b/Terminal.Gui/Views/SaveDialog.cs
@@ -42,7 +42,7 @@ namespace Terminal.Gui {
{
//: base (title, prompt: Strings.fdSave, nameFieldLabel: $"{Strings.fdSaveAs}:", message: message, allowedTypes) { }
Title = title;
- Style.OkButtonText = Strings.fdSave;
+ Style.OkButtonText = Strings.btnSave;
if(allowedTypes != null) {
AllowedTypes = allowedTypes;
@@ -62,5 +62,24 @@ namespace Terminal.Gui {
return Path;
}
}
+
+ protected override string GetDefaultTitle ()
+ {
+ List titleParts = new () {
+ Strings.fdSave
+ };
+ if (MustExist) {
+ titleParts.Add (Strings.fdExisting);
+ }
+ switch (OpenMode) {
+ case OpenMode.File:
+ titleParts.Add (Strings.fdFile);
+ break;
+ case OpenMode.Directory:
+ titleParts.Add (Strings.fdDirectory);
+ break;
+ }
+ return string.Join (' ', titleParts);
+ }
}
}
diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs
index 8fb9a2156..1d66b853d 100644
--- a/Terminal.Gui/Views/StatusBar.cs
+++ b/Terminal.Gui/Views/StatusBar.cs
@@ -27,11 +27,13 @@ namespace Terminal.Gui {
/// Shortcut to activate the .
/// Title for the .
/// Action to invoke when the is activated.
- public StatusItem (Key shortcut, string title, Action action)
+ /// Function to determine if the action can currently be executed.
+ public StatusItem (Key shortcut, string title, Action action, Func canExecute = null)
{
Title = title ?? "";
Shortcut = shortcut;
Action = action;
+ CanExecute = canExecute;
}
///
@@ -54,7 +56,22 @@ namespace Terminal.Gui {
/// Gets or sets the action to be invoked when the statusbar item is triggered
///
/// Action to invoke.
- public Action Action { get; }
+ public Action Action { get; set; }
+
+ ///
+ /// Gets or sets the action to be invoked to determine if the can be triggered.
+ /// If returns the status item will be enabled. Otherwise, it will be disabled.
+ ///
+ /// Function to determine if the action is can be executed or not.
+ public Func CanExecute { get; set; }
+
+ ///
+ /// Returns if the status item is enabled. This method is a wrapper around .
+ ///
+ public bool IsEnabled ()
+ {
+ return CanExecute == null ? true : CanExecute ();
+ }
///
/// Gets or sets arbitrary data for the status item.
@@ -116,6 +133,17 @@ namespace Terminal.Gui {
return result;
}
+ Attribute DetermineColorSchemeFor (StatusItem item)
+ {
+ if (item != null) {
+ if (item.IsEnabled ()) {
+ return GetNormalColor ();
+ }
+ return ColorScheme.Disabled;
+ }
+ return GetNormalColor ();
+ }
+
///
public override void OnDrawContent (Rect contentArea)
{
@@ -130,9 +158,12 @@ namespace Terminal.Gui {
Driver.SetAttribute (scheme);
for (int i = 0; i < Items.Length; i++) {
var title = Items [i].Title;
+ Driver.SetAttribute (DetermineColorSchemeFor (Items [i]));
for (int n = 0; n < Items [i].Title.GetRuneCount (); n++) {
if (title [n] == '~') {
- scheme = ToggleScheme (scheme);
+ if (Items [i].IsEnabled ()) {
+ scheme = ToggleScheme (scheme);
+ }
continue;
}
Driver.AddRune ((Rune)title [n]);
@@ -150,7 +181,9 @@ namespace Terminal.Gui {
{
foreach (var item in Items) {
if (kb.Key == item.Shortcut) {
- Run (item.Action);
+ if (item.IsEnabled ()) {
+ Run (item.Action);
+ }
return true;
}
}
@@ -166,7 +199,10 @@ namespace Terminal.Gui {
int pos = 1;
for (int i = 0; i < Items.Length; i++) {
if (me.X >= pos && me.X < pos + GetItemTitleLength (Items [i].Title)) {
- Run (Items [i].Action);
+ var item = Items [i];
+ if (item.IsEnabled ()) {
+ Run (item.Action);
+ }
break;
}
pos += GetItemTitleLength (Items [i].Title) + 3;
diff --git a/Terminal.sln b/Terminal.sln
index 2474410eb..990626580 100644
--- a/Terminal.sln
+++ b/Terminal.sln
@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\dotnet-core.yml = .github\workflows\dotnet-core.yml
GitVersion.yml = GitVersion.yml
global.json = global.json
+ nuget.config = nuget.config
.github\workflows\publish.yml = .github\workflows\publish.yml
README.md = README.md
Terminal.sln.DotSettings = Terminal.sln.DotSettings
diff --git a/UICatalog/Scenarios/Localization.cs b/UICatalog/Scenarios/Localization.cs
new file mode 100644
index 000000000..fe2fca3ac
--- /dev/null
+++ b/UICatalog/Scenarios/Localization.cs
@@ -0,0 +1,181 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+ [ScenarioMetadata (Name: "Localization", Description: "Test for localization resources.")]
+ [ScenarioCategory ("Text and Formatting")]
+ [ScenarioCategory ("Tests")]
+ public class Localization : Scenario {
+ public CultureInfo CurrentCulture { get; private set; } = Thread.CurrentThread.CurrentUICulture;
+
+ private CultureInfo [] _cultureInfoSource;
+ private string [] _cultureInfoNameSource;
+ private ComboBox _languageComboBox;
+ private CheckBox _allowAnyCheckBox;
+ private OpenMode _currentOpenMode = OpenMode.File;
+
+ public override void Setup ()
+ {
+ base.Setup ();
+ _cultureInfoSource = Application.SupportedCultures.Append (CultureInfo.InvariantCulture).ToArray ();
+ _cultureInfoNameSource = Application.SupportedCultures.Select (c => $"{c.NativeName} ({c.Name})").Append ("Invariant").ToArray ();
+ var languageMenus = Application.SupportedCultures
+ .Select (c => new MenuItem ($"{c.NativeName} ({c.Name})", "", () => SetCulture (c)))
+ .Concat (
+ new MenuItem [] {
+ null,
+ new MenuItem ("Invariant", "", () => SetCulture (CultureInfo.InvariantCulture))
+ }
+ )
+ .ToArray ();
+ var menu = new MenuBar (new MenuBarItem [] {
+ new MenuBarItem ("_File", new MenuItem [] {
+ new MenuBarItem("_Language", languageMenus),
+ null,
+ new MenuItem ("_Quit", "", Quit),
+ }),
+ });
+ Application.Top.Add (menu);
+
+ var selectLanguageLabel = new Label ("Please select a language.") {
+ X = 2,
+ Y = 1,
+ Width = Dim.Fill (2),
+ AutoSize = true
+ };
+ Win.Add (selectLanguageLabel);
+
+ _languageComboBox = new ComboBox (_cultureInfoNameSource) {
+ X = 2,
+ Y = Pos.Bottom (selectLanguageLabel) + 1,
+ Width = _cultureInfoNameSource.Select (cn => cn.Length + 3).Max (),
+ Height = _cultureInfoNameSource.Length + 1,
+ HideDropdownListOnClick = true,
+ AutoSize = true,
+ SelectedItem = _cultureInfoNameSource.Length - 1
+ };
+ _languageComboBox.SelectedItemChanged += LanguageComboBox_SelectChanged;
+ Win.Add (_languageComboBox);
+
+ var textAndFileDialogLabel = new Label ("Right click on the text field to open a context menu, click the button to open a file dialog.\r\nOpen mode will loop through 'File', 'Directory' and 'Mixed' as 'Open' or 'Save' button clicked.") {
+ X = 2,
+ Y = Pos.Top (_languageComboBox) + 3,
+ Width = Dim.Fill (2),
+ AutoSize = true
+ };
+ Win.Add (textAndFileDialogLabel);
+
+ var textField = new TextView {
+ X = 2,
+ Y = Pos.Bottom (textAndFileDialogLabel) + 1,
+ Width = Dim.Fill (32),
+ Height = 1
+ };
+ Win.Add (textField);
+
+ _allowAnyCheckBox = new CheckBox {
+ X = Pos.Right (textField) + 1,
+ Y = Pos.Bottom (textAndFileDialogLabel) + 1,
+ Checked = false,
+ Text = "Allow any"
+ };
+ Win.Add (_allowAnyCheckBox);
+
+ var openDialogButton = new Button ("Open") {
+ X = Pos.Right (_allowAnyCheckBox) + 1,
+ Y = Pos.Bottom (textAndFileDialogLabel) + 1
+ };
+ openDialogButton.Clicked += (sender, e) => ShowFileDialog (false);
+ Win.Add (openDialogButton);
+
+ var saveDialogButton = new Button ("Save") {
+ X = Pos.Right (openDialogButton) + 1,
+ Y = Pos.Bottom (textAndFileDialogLabel) + 1
+ };
+ saveDialogButton.Clicked += (sender, e) => ShowFileDialog (true);
+ Win.Add (saveDialogButton);
+
+ var wizardLabel = new Label ("Click the button to open a wizard.") {
+ X = 2,
+ Y = Pos.Bottom (textField) + 1,
+ Width = Dim.Fill (2),
+ AutoSize = true
+ };
+ Win.Add (wizardLabel);
+
+ var wizardButton = new Button ("Open _wizard") {
+ X = 2,
+ Y = Pos.Bottom (wizardLabel) + 1
+ };
+ wizardButton.Clicked += (sender, e) => ShowWizard ();
+ Win.Add (wizardButton);
+
+ Win.Unloaded += (sender, e) => Quit ();
+ }
+
+ public void SetCulture (CultureInfo culture)
+ {
+ if (_cultureInfoSource [_languageComboBox.SelectedItem] != culture) {
+ _languageComboBox.SelectedItem = Array.IndexOf (_cultureInfoSource, culture);
+ }
+ if (this.CurrentCulture == culture) return;
+ this.CurrentCulture = culture;
+ Thread.CurrentThread.CurrentUICulture = culture;
+ Application.Refresh ();
+ }
+ private void LanguageComboBox_SelectChanged (object sender, ListViewItemEventArgs e)
+ {
+ if (e.Value is string cultureName) {
+ var index = Array.IndexOf (_cultureInfoNameSource, cultureName);
+ if (index >= 0) {
+ SetCulture (_cultureInfoSource [index]);
+ }
+ }
+ }
+ public void ShowFileDialog (bool isSaveFile)
+ {
+ FileDialog dialog = isSaveFile ? new SaveDialog () : new OpenDialog ("", null, _currentOpenMode);
+ dialog.AllowedTypes = new List () {
+ (_allowAnyCheckBox.Checked ?? false) ? new AllowedTypeAny() : new AllowedType("Dynamic link library", ".dll"),
+ new AllowedType("Json", ".json"),
+ new AllowedType("Text", ".txt"),
+ new AllowedType("Yaml", ".yml", ".yaml")
+ };
+ dialog.MustExist = !isSaveFile;
+ dialog.AllowsMultipleSelection = !isSaveFile;
+ _currentOpenMode++;
+ if (_currentOpenMode > OpenMode.Mixed) {
+ _currentOpenMode = OpenMode.File;
+ }
+ Application.Run (dialog);
+ }
+ public void ShowWizard ()
+ {
+ Wizard wizard = new Wizard {
+ Height = 8,
+ Width = 36,
+ Title = "The wizard"
+ };
+ wizard.AddStep (new WizardStep () {
+ HelpText = "Wizard first step",
+ });
+ wizard.AddStep (new WizardStep () {
+ HelpText = "Wizard step 2",
+ NextButtonText = ">>> (_N)"
+ });
+ wizard.AddStep (new WizardStep () {
+ HelpText = "Wizard last step"
+ });
+ Application.Run (wizard);
+ }
+ public void Quit ()
+ {
+ SetCulture (CultureInfo.InvariantCulture);
+ Application.RequestStop ();
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnitTests/Views/DateFieldTests.cs b/UnitTests/Views/DateFieldTests.cs
index e32897a77..26774ed88 100644
--- a/UnitTests/Views/DateFieldTests.cs
+++ b/UnitTests/Views/DateFieldTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -59,6 +60,8 @@ namespace Terminal.Gui.ViewsTests {
[Fact]
public void KeyBindings_Command ()
{
+ CultureInfo cultureBackup = CultureInfo.CurrentCulture;
+ CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
DateField df = new DateField (DateTime.Parse ("12/12/1971"));
df.ReadOnly = true;
Assert.True (df.ProcessKey (new KeyEvent (Key.DeleteChar, new KeyModifiers ())));
@@ -93,6 +96,7 @@ namespace Terminal.Gui.ViewsTests {
df.ReadOnly = false;
Assert.True (df.ProcessKey (new KeyEvent (Key.D1, new KeyModifiers ())));
Assert.Equal (" 12/02/1971", df.Text);
+ CultureInfo.CurrentCulture = cultureBackup;
}
}
}
diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs
index 06ef9d597..d2e81ead1 100644
--- a/UnitTests/Views/StatusBarTests.cs
+++ b/UnitTests/Views/StatusBarTests.cs
@@ -23,7 +23,7 @@ namespace Terminal.Gui.ViewsTests {
}
[Fact]
- public void StatusBar_Contructor_Default ()
+ public void StatusBar_Constructor_Default ()
{
var sb = new StatusBar ();
@@ -160,5 +160,43 @@ CTRL-O Open {CM.Glyphs.VLine} CTRL-Q Quit
Assert.Equal ("~^A~ Save As", sb.Items [1].Title);
Assert.Equal ("~^Q~ Quit", sb.Items [^1].Title);
}
+
+ [Fact, AutoInitShutdown]
+ public void CanExecute_ProcessHotKey ()
+ {
+ Window win = null;
+ var statusBar = new StatusBar (new StatusItem [] {
+ new StatusItem (Key.CtrlMask | Key.N, "~^N~ New", New, CanExecuteNew),
+ new StatusItem (Key.CtrlMask | Key.C, "~^C~ Close", Close, CanExecuteClose)
+ });
+ var top = Application.Top;
+ top.Add (statusBar);
+
+ bool CanExecuteNew () => win == null;
+
+ void New ()
+ {
+ win = new Window ();
+ }
+
+ bool CanExecuteClose () => win != null;
+
+ void Close ()
+ {
+ win = null;
+ }
+
+ Application.Begin (top);
+
+ Assert.Null (win);
+ Assert.True (CanExecuteNew ());
+ Assert.False (CanExecuteClose ());
+
+ Assert.True (top.ProcessHotKey (new KeyEvent (Key.N | Key.CtrlMask, new KeyModifiers () { Alt = true })));
+ Application.MainLoop.RunIteration ();
+ Assert.NotNull (win);
+ Assert.False (CanExecuteNew ());
+ Assert.True (CanExecuteClose ());
+ }
}
}
diff --git a/nuget.config b/nuget.config
new file mode 100644
index 000000000..7d1098866
--- /dev/null
+++ b/nuget.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+