Files
Terminal.Gui/UICatalog/Scenarios/ConfigurationEditor.cs
Tig dcb3b359ad Fixes #2926 - Refactor KeyEvent and KeyEventEventArgs to simplify (#2927)
* Adds basic MainLoop unit tests

* Remove WinChange action from Curses

* Remove WinChange action from Curses

* Remove ProcessInput action from Windows MainLoop

* Simplified MainLoop/ConsoleDriver by making MainLoop internal and moving impt fns to Application

* Modernized Terminal resize events

* Modernized Terminal resize events

* Removed un used property

* for _isWindowsTerminal devenv->wininit; not sure what changed

* Modernized mouse/keyboard events (Action->EventHandler)

* Updated OnMouseEvent API docs

* Using WT_SESSION to detect WT

* removes hacky GetParentProcess

* Updates to fix #2634 (clear last line)

* removes hacky GetParentProcess2

* Addressed mac resize issue

* Addressed mac resize issue

* Removes ConsoleDriver.PrepareToRun, has Init return MainLoop

* Removes unneeded Attribute methods

* Removed GetProcesssName

* Removed GetProcesssName

* Refactored KeyEvent and KeyEventEventArgs into a single class

* Revert "Refactored KeyEvent and KeyEventEventArgs into a single class"

This reverts commit 88a00658db.

* Fixed key repeat issue; reverted stupidity on 1049/1047 confusion

* Updated CSI API Docs

* merge

* Rearranged Event.cs to Keyboard.cs and Mouse.cs

* Renamed KeyEventEventArgs KeyEventArgs

* temp renamed KeyEvent OldKeyEvent

* Merged KeyEvent into KeyEventArgs

* Renamed Application.ProcessKey members

* Renamed Application.ProcessKey members

* Renamed Application.ProcessKey members

* Added Responder.KeyPressed

* Removed unused references

* Fixed arg naming

* InvokeKeybindings->InvokeKeyBindings

* InvokeKeybindings->InvokeKeyBindings

* Fixed unit tests fail

* More progress on refactoring key input; still broken and probably wrong

* Moved OnKeyPressed out of Responder and made ProcessKeyPrssed non-virtual

* Updated API docs

* Moved key handling from Responder to View

* Updated API docs

* Updated HotKey API docs

* Updated shortcut API docs

* Fixed responder unit tests

* Removed Shortcut from View as it is not used

* Removed unneeded OnHotKey override from Button

* Fixed BackTab logic

* Button now uses Key Bindings exclusively

* Button now uses Key Bindings exclusively

* Updated keyboard.md docs

* Fixed unit tests to account for Toplevel handling default button

* Added View.InvokeCommand API

* Modernized RadioGroup

* Removed ColdKey

* Modernized (partially) StatusBar

* Worked around FileDialog issue with Ctrl-F

* Fixed driver unit test; view must be focused to reciev key pressed

* Application code cleanup

* Start on updaing menu

* Menu now mostly works

* Menu Select refinement

* Fixed known menu bugs!

* Enabled HotKey to cause focus- experimental

* Fixes #3022 & adds unit test to prove it

* Actually Fixes #3022 & adds unit test to prove it

* Working through hotkey issues

* Misc fixes

* removed hot/cold key stuff from Keys scenario

* Fixed scenarios

* Simplified shortcut string handling

* Modernized Checkbox

* Modernized TileView

* Updated API docs

* Updated API docs

* attempting to publish v2 docs

* Revert "attempting to publish v2 docs"

This reverts commit 59dcec111b.

* Playing with api docs

* Removed Key.BackTab

* Removed Caps/Scroll/Numlock

* Partial removal of keymodifiers - unit tests pass

* Partial removal of keymodifiers - broke netdriver somewhere

* WindowsDriver & added KeyEventArgsTests

* Fixing menu shortcut/hotkeys - broke Menu.cs into separate files

* Fixed MenuBar!

* Finished modernizing Menu/MenuBar

* Removed Key.a-z. Broke lots of stuff

* checkout@v4

* progress on key mapping and formatting

* VK tests are still failing

* Fixed some unit tests

* Added Hotkey and Keybinding unit tests

* fixed unit test

* All unit tests pass again...

* Fixed broken unit tests

* KeyEventArgs.KeyValue -> AsRune

* Fixed bugs. Still some broken

* Added KeyEventArgs.IsAlpha. Added KeyEventArgs.cast ops. Fixed bugs. Unit tests pass

* Fixed WindowsDriver

* Oops.

* Refactoring based on bdisp's help. Not complete!

* removed calling into subviews from OnKeyBindings

* removed calling into subviews from OnKeyBindings

* Improved View KeyEvent unit tests

* More hotkey unit tests

* BIg change - Got rid of KeyPress w/in Application/Drivers

* Unit tests now pass again

* Refreshed API docs

* Better HotKey logic. More progress. Getting close.

* Fixed handling of shifted chars like ö

* Minor code cleanup

* Minor code cleanup2

* Why is build Action failing?

* Why is build Action failing??

* upgraded to .net8 to try to fix weird CI/CD build errors

* upgraded to .net8 to try to fix weird CI/CD build errors2

* Disabling TextViewTests to diagnose build errors

* reenable TextViewTests to diagnose build errors

* Arrrrrrg

* Merged v2_develop

* Fixed uppercase accented keys in WindowsDriver

* Fixed key binding api docs

* Experimental impl of CommandScope.SubViews for MenuBar

* Removed dead code from application.cs

* Removed dead code from application.cs

* Removed dead code from ConsoleDriver.cs

* Cleaned up some key binding stuff

* Disabled Alt to activate menu for now

* Updated label commands

* Fixed menu bugs. Upgraded menu unit tests

* Fixed unit tests

* Working on NetDriver

* fixed netdriver

* Fixed issues called out by @bdisp CR

* fixed CursesDriver

* added todo to netdriver

* Cherry picked treeview test fix 1b415e5

* Fix NetDriver.

* CommandScope->KeyBindingScope

* Address some tznind feedback

* Refactored KeyBindings big time!

* Added key consts to KeyEventArgs and renamed Key to ConsoleDriverKey

* Fixed some API docs

* Moved ConsoleDriverKey to ConsoleDriver.cs

* Renamed Key->ConsoleDriverKey

* Renamed Key->ConsoleDriverKey

* Renamed Key->ConsoleDriverKey

* renamed file I forgot to rename before

* Updated name and API docs of KeyEventArgs.isAlpha

* Fixed issues with OnKeyUp not doing the right thing.

* Fixed MainLoop.Running never being used

* Fixed MainLoop.Running never being used - unit tests

* Claned up BUGBUG comments

* Disabled a unit test to see why ci/cd tests are failing

* Removed defunct commented code

* Removed more defunct commented code

* Re-eanbled unit test; jsut removing one test case...

* Disabled more...

* Renambed Global->Applicaton and updated scope API docs

* Disabled more unit tests...

* Removed dead code

* Disabled more unit tests...2

* Disabled more unit tests...3

* Renambed Global->Applicaton and updated scope API docs 2

* Added more KeyBinding scope tests

* Added more KeyBinding scope tests2

* ConsoleDriverKey too long. Key too ambiguous. Settled on KeyCode. (Partialy because eventually I want to intro a class named Key).

* KeyEventArgs improvements. cast to Rune must be explicit as it's lossy

* Fixed warnings

* Renamed KeyEventArgs to Key... progress on fixing broken stuff that resulted

* Fix ConsoleKeyMapping bugs.

* Fix NetDriver issue from converting a lower case to a upper case.

* Started migration to Key from KeyCode - e.g. made HotKeys all consistent.

* Fixed build warnings

* Added key defns to Key

* KeyBindings now uses Key vs. KeyCode

* Verified by tweaking UICatalog

* Fixed treeview test ... again

* Renamed ProcessKeyDown/Up to NewKeyDown/Up and OnKeyPressed to OnProcessKeyDown to make things more clear

* Added test AllViews_KeyDown_All_EventsFire unit tests and fixed a few Views that were wrong

* fixed stupid KeyUp event bug

* If key not handled, return false for datefield

* dotnet test --no-restore --verbosity diag

* dotnet test --blame

* run tests on windows

* Fix TestVKPacket unit test and move it to ConsoleKeyMappingTests.cs file.

* Remove unnecessary commented code.

* Tweaked unit tests and removed Key.BareKey

* Fixed little details and updated api docs

* updated api docs

* AddKeyBindingsForHotKey: KeyCode->Key

* Cleaned up more old KeyCode usages. Added TODOs

---------

Co-authored-by: BDisp <bd.bdisp@gmail.com>
2023-12-16 12:04:23 -07:00

207 lines
5.4 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Terminal.Gui;
namespace UICatalog.Scenarios {
[ScenarioMetadata (Name: "Configuration Editor", Description: "Edits Terminal.Gui Config Files.")]
[ScenarioCategory ("TabView"), ScenarioCategory ("Colors"), ScenarioCategory ("Files and IO"), ScenarioCategory ("TextView")]
public class ConfigurationEditor : Scenario {
TileView _tileView;
StatusItem _lenStatusItem;
private static ColorScheme _editorColorScheme = new ColorScheme () {
Normal = new Attribute (Color.Red, Color.White),
Focus = new Attribute (Color.Red, Color.Black),
HotFocus = new Attribute (Color.BrightRed, Color.Black),
HotNormal = new Attribute (Color.Magenta, Color.White)
};
[SerializableConfigurationProperty (Scope = typeof (AppScope))]
public static ColorScheme EditorColorScheme {
get => _editorColorScheme;
set {
_editorColorScheme = value;
_editorColorSchemeChanged?.Invoke ();
}
}
private static Action _editorColorSchemeChanged;
// Don't create a Window, just return the top-level view
public override void Init ()
{
Application.Init ();
ConfigurationManager.Themes.Theme = Theme;
ConfigurationManager.Apply ();
Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
}
public override void Setup ()
{
_tileView = new TileView (0) {
Width = Dim.Fill (),
Height = Dim.Fill (1),
Orientation = Orientation.Vertical,
LineStyle = LineStyle.Single
};
Application.Top.Add (_tileView);
_lenStatusItem = new StatusItem (KeyCode.CharMask, "Len: ", null);
var statusBar = new StatusBar (new StatusItem [] {
new StatusItem(Application.QuitKey, $"{Application.QuitKey} Quit", () => Quit()),
new StatusItem(KeyCode.F5, "~F5~ Reload", () => Reload()),
new StatusItem(KeyCode.CtrlMask | KeyCode.S, "~^S~ Save", () => Save()),
_lenStatusItem,
});
Application.Top.Add (statusBar);
Application.Top.Loaded += (s, a) => Open ();
ConfigurationEditor._editorColorSchemeChanged += () => {
foreach (var t in _tileView.Tiles) {
t.ContentView.ColorScheme = ConfigurationEditor.EditorColorScheme;
t.ContentView.SetNeedsDisplay ();
};
};
ConfigurationEditor._editorColorSchemeChanged.Invoke ();
}
private class ConfigTextView : TextView {
internal Tile Tile { get; set; }
internal FileInfo FileInfo { get; set; }
internal ConfigTextView ()
{
ContentsChanged += (s, obj) => {
if (IsDirty) {
if (!Tile.Title.EndsWith ('*')) {
Tile.Title += '*';
} else {
Tile.Title = Tile.Title.TrimEnd ('*');
}
}
};
}
internal void Read ()
{
Assembly assembly = null;
if (FileInfo.FullName.Contains ("[Terminal.Gui]")) {
// Library resources
assembly = typeof (ConfigurationManager).Assembly;
} else if (FileInfo.FullName.Contains ("[UICatalog]")) {
assembly = Assembly.GetEntryAssembly ();
}
if (assembly != null) {
string name = assembly
.GetManifestResourceNames ()
.FirstOrDefault (x => x.EndsWith ("config.json"));
using Stream stream = assembly.GetManifestResourceStream (name);
using StreamReader reader = new StreamReader (stream);
Text = reader.ReadToEnd ();
ReadOnly = true;
Enabled = true;
return;
}
if (!FileInfo.Exists) {
// Create empty config file
Text = ConfigurationManager.GetEmptyJson ();
} else {
Text = File.ReadAllText (FileInfo.FullName);
}
Tile.Title = Tile.Title.TrimEnd ('*');
}
internal void Save ()
{
if (!Directory.Exists (FileInfo.DirectoryName)) {
// Create dir
Directory.CreateDirectory (FileInfo.DirectoryName!);
}
using var writer = File.CreateText (FileInfo.FullName);
writer.Write (Text);
writer.Close ();
Tile.Title = Tile.Title.TrimEnd ('*');
IsDirty = false;
}
}
private void Open ()
{
var subMenu = new MenuBarItem () {
Title = "_View",
};
foreach (var configFile in ConfigurationManager.Settings.Sources) {
var homeDir = $"{Environment.GetFolderPath (Environment.SpecialFolder.UserProfile)}";
FileInfo fileInfo = new FileInfo (configFile.Replace ("~", homeDir));
var tile = _tileView.InsertTile (_tileView.Tiles.Count);
tile.Title = configFile.StartsWith ("resource://") ? fileInfo.Name : configFile;
var textView = new ConfigTextView () {
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill (),
FileInfo = fileInfo,
Tile = tile
};
tile.ContentView.Add (textView);
textView.Read ();
textView.Enter += (s, e) => {
_lenStatusItem.Title = $"Len:{textView.Text.Length}";
};
}
Application.Top.LayoutSubviews ();
}
private void Reload ()
{
if (_tileView.MostFocused is ConfigTextView editor) {
editor.Read ();
}
}
public void Save ()
{
if (_tileView.MostFocused is ConfigTextView editor) {
editor.Save ();
}
}
private void Quit ()
{
foreach (var tile in _tileView.Tiles) {
ConfigTextView editor = tile.ContentView.Subviews [0] as ConfigTextView;
if (editor.IsDirty) {
int result = MessageBox.Query ("Save Changes", $"Save changes to {editor.FileInfo.FullName}", "Yes", "No", "Cancel");
if (result == -1 || result == 2) {
// user cancelled
}
if (result == 0) {
editor.Save ();
}
}
}
Application.RequestStop ();
}
}
}