Skip to content

Adds keybindings configuration window #311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Design.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public class Design
typeof(TabView),
typeof(Window),
typeof(Toplevel),
typeof(View),
typeof(GraphView),
typeof(HexView),
typeof(LineView),
Expand Down
64 changes: 57 additions & 7 deletions src/UI/Editor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
Expand All @@ -21,7 +22,7 @@ namespace TerminalGuiDesigner.UI;
/// </summary>
public class Editor : Toplevel
{
private readonly KeyMap keyMap;
private KeyMap keyMap;
private readonly KeyboardManager keyboardManager;
private readonly MouseManager mouseManager;

Expand All @@ -46,6 +47,7 @@ public class Editor : Toplevel
/// </summary>
internal Guid? LastSavedOperation;

private static string _keymapPath = string.Empty;
private static string _logDirectory = string.Empty;

/// <summary>
Expand All @@ -66,9 +68,32 @@ public Editor()
Logging.Logger = CreateLogger();
}

LoadKeyMap();

this.keyboardManager = new KeyboardManager(this.keyMap);
this.mouseManager = new MouseManager();
this.Closing += this.Editor_Closing;

this.BuildRootMenu();
}

private void LoadKeyMap()
{
_keymapPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"TerminalGuiDesigner", "keymap.json");

try
{
this.keyMap = new ConfigurationBuilder( ).AddYamlFile( "Keys.yaml", true ).Build( ).Get<KeyMap>( ) ?? new( );
if (File.Exists(_keymapPath))
{
var json = File.ReadAllText(_keymapPath);
this.keyMap = JsonSerializer.Deserialize<KeyMap>(json) ?? new KeyMap();
}
else
{
this.keyMap = new KeyMap();
}

SelectionManager.Instance.SelectedScheme = this.keyMap.SelectionColor.Scheme;
}
Expand All @@ -78,12 +103,21 @@ public Editor()
ExceptionViewer.ShowException("Failed to read keybindings from configuration file", ex);
this.keyMap = new KeyMap();
}
}

this.keyboardManager = new KeyboardManager(this.keyMap);
this.mouseManager = new MouseManager();
this.Closing += this.Editor_Closing;

this.BuildRootMenu();
private void SaveKeyMap()
{
try
{
var json = JsonSerializer.Serialize(this.keyMap);
File.WriteAllText(_keymapPath, json);
SelectionManager.Instance.SelectedScheme = this.keyMap.SelectionColor.Scheme;
}
catch (Exception ex)
{
ExceptionViewer.ShowException("Failed to save keybindings from configuration file", ex);
}
}

static ILogger CreateLogger()
Expand Down Expand Up @@ -769,6 +803,7 @@ private void BuildRootMenu()
$"{this.keyMap.ShowHelp} - Show Help",
$"{this.keyMap.New} - New Window/Class",
$"{this.keyMap.Open} - Open a .Designer.cs file",
$"Keybindings",
};

// center all the commands
Expand All @@ -783,7 +818,7 @@ private void BuildRootMenu()
X = Pos.Center(),
Y = Pos.Percent(75),
Width = maxWidth,
Height = 3,
Height = 4,
ColorScheme = new ColorScheme
(
new Attribute(new Color(Color.White),new Color(Color.Black)),
Expand Down Expand Up @@ -813,6 +848,9 @@ private void BuildRootMenu()
case 2:
this.Open();
break;
case 3:
this.ChangeKeybindings();
break;
}
}

Expand All @@ -836,6 +874,18 @@ private void BuildRootMenu()
this.Add(this.rootCommandsListView);
}

private void ChangeKeybindings()
{
var kb = new KeyBindingsUI(keyMap);
Application.Run(kb);

if (kb.Save)
{
SaveKeyMap();
}
}


private void Editor_Closing(object? sender, ToplevelClosingEventArgs obj)
{
if (this.viewBeingEdited == null)
Expand Down
151 changes: 151 additions & 0 deletions src/UI/Windows/KeyBindingsUI.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 100 additions & 0 deletions src/UI/Windows/KeyBindingsUI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@

//------------------------------------------------------------------------------

// <auto-generated>
// This code was generated by:
// TerminalGuiDesigner v2.0.0.0
// You can make changes to this file and they will not be overwritten when saving.
// </auto-generated>
// -----------------------------------------------------------------------------

using System.Reflection;
using System.Text.Json;

namespace TerminalGuiDesigner.UI.Windows {
using Terminal.Gui;


public partial class KeyBindingsUI {
private readonly KeyMap keyMap;
private readonly PropertyInfo[] _props;

public bool Save { get; set; } = false;

public KeyBindingsUI(KeyMap keyMap) {
this.keyMap = keyMap;
InitializeComponent();

_props = typeof(KeyMap).GetProperties()
.Where(p=>p.PropertyType == typeof(string))
.OrderBy(p=>p.Name)
.ToArray();

tableView.Table = new EnumerableTableSource<PropertyInfo>(_props,
new Dictionary<string, Func<PropertyInfo, object>>()
{
{ "Function", p => p.Name },
{ "Key", p => p.GetValue(this.keyMap) }
});

var keyStyle = tableView.Style.GetOrCreateColumnStyle(1);

var badCellColor = CloneColorSchemeButMake(tableView.ColorScheme,Color.Red);

keyStyle.ColorGetter = (k) =>
{
var val = _props[k.RowIndex].GetValue(this.keyMap);
var matches = _props.Select(k => k.GetValue(this.keyMap)).Count(v => Equals(v,val));
if (matches > 1)
{
return badCellColor;
}

// Use normal color scheme
return null;
};

tableView.CellActivated += (s, e) =>
{
var prop = _props[e.Row];
var k = Modals.GetShortcut();
prop.SetValue(this.keyMap,k.ToString());
this.SetNeedsDraw();
};
btnReset.Accepting += (s, e) =>
{
var defaultMap = new KeyMap();
foreach (var p in _props)
{
var def = p.GetValue(defaultMap);
p.SetValue(this.keyMap, def);
this.SetNeedsDraw();
}
};

btnSave.Accepting += (s, e) =>
{
Save = true;
e.Cancel = true;
Application.RequestStop();
};
btnCancel.Accepting += (s, e) =>
{
e.Cancel = true;
Application.RequestStop();
};
}

private ColorScheme CloneColorSchemeButMake(ColorScheme cs,Color color)
{
return new ColorScheme
{
Disabled = cs.Disabled,
Focus = cs.Focus,
HotFocus = cs.HotFocus,
HotNormal = cs.HotNormal,
Normal = new Attribute(color, cs.Normal.Background)
};
}
}
}
Loading
Loading