Skip to content

Commit

Permalink
Add shortcut components
Browse files Browse the repository at this point in the history
  • Loading branch information
paralleltree committed May 6, 2021
1 parent 6014db8 commit cb268a9
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Ched/Ched.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@
<Compile Include="Plugins\SlideSplitter.cs" />
<Compile Include="Plugins\SusExportPlugin.cs" />
<Compile Include="UI\Helpers.cs" />
<Compile Include="UI\Shortcuts\ShortcutCommandSource.cs" />
<Compile Include="UI\Shortcuts\ShortcutKeySource.cs" />
<Compile Include="UI\Shortcuts\ShortcutManager.cs" />
<Compile Include="UI\Windows\Behaviors\InitialFocusBehavior.cs" />
<Compile Include="UI\Windows\Behaviors\OpenFileBehavior.cs" />
<Compile Include="UI\Windows\Behaviors\StyleBehaviorCollection.cs" />
Expand Down
33 changes: 33 additions & 0 deletions Ched/UI/Shortcuts/ShortcutCommandSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Ched.UI.Shortcuts
{
public interface IShortcutCommandSource
{
/// <summary>
/// 指定のコマンドを実行します。
/// </summary>
/// <param name="command">実行するコマンド</param>
/// <returns>コマンドが実行された場合はTrue</returns>
bool ExecuteCommand(string command);

bool ResolveCommandName(string command, out string name);
}

public class NullShortcutCommandSource : IShortcutCommandSource
{
// Do nothing
public bool ExecuteCommand(string command) => true;

public bool ResolveCommandName(string command, out string name)
{
name = null;
return false;
}
}
}
86 changes: 86 additions & 0 deletions Ched/UI/Shortcuts/ShortcutKeySource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Ched.UI.Shortcuts
{
public interface IShortcutKeySource
{
/// <summary>
/// 指定のショートカットキーに対応するコマンドを取得します。
/// </summary>
/// <param name="key">コマンドを取得するショートカットキー</param>
/// <param name="command">ショートカットキーに対応するコマンド</param>
/// <returns>ショートカットキーに対応するコマンドが存在すればTrue</returns>
bool ResolveCommand(Keys key, out string command);

/// <summary>
/// 指定のコマンドに対応するショートカットキーを取得します。
/// </summary>
/// <param name="command">ショートカットキーを取得するコマンド</param>
/// <param name="key">コマンドに対応するショートカットキー</param>
/// <returns>コマンドに対応するショートカットキーが存在すればTrue</returns>
bool ResolveShortcutKey(string command, out Keys key);
}

public class NullShortcutKeySource : IShortcutKeySource
{
public bool ResolveCommand(Keys key, out string command)
{
command = null;
return false;
}

public bool ResolveShortcutKey(string command, out Keys key)
{
key = Keys.None;
return false;
}
}

public abstract class ShortcutKeySource : IShortcutKeySource
{
private Dictionary<Keys, string> KeyMap { get; } = new Dictionary<Keys, string>();
private Dictionary<string, HashSet<Keys>> CommandMap { get; } = new Dictionary<string, HashSet<Keys>>();

public IEnumerable<Keys> ShortcutKeys => KeyMap.Keys;

public ShortcutKeySource()
{
}

protected ShortcutKeySource(ShortcutKeySource other)
{
foreach (var item in other.KeyMap)
{
RegisterShortcut(item.Value, item.Key);
}
}

protected void RegisterShortcut(string command, Keys key)
{
// キーの重複を確認。コマンドは重複してもよい(異なるキーから同じコマンドを呼び出しても問題ない)
if (KeyMap.ContainsKey(key)) throw new InvalidOperationException("The shortcut key has already been registered.");
KeyMap.Add(key, command);
if (!CommandMap.ContainsKey(command)) CommandMap.Add(command, new HashSet<Keys>());
CommandMap[command].Add(key);
}

public bool ResolveCommand(Keys key, out string command) => KeyMap.TryGetValue(key, out command);

public bool ResolveShortcutKey(string command, out Keys key)
{
key = Keys.None;
if (!CommandMap.TryGetValue(command, out HashSet<Keys> keys)) return false;
if (keys.Count > 0)
{
key = keys.First();
return true;
}
return false;
}
}
}
36 changes: 36 additions & 0 deletions Ched/UI/Shortcuts/ShortcutManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Ched.UI.Shortcuts
{
public class ShortcutManager
{
public IShortcutCommandSource CommandSource { get; set; } = new NullShortcutCommandSource();
public IShortcutKeySource DefaultKeySource { get; set; } = new NullShortcutKeySource();
public IShortcutKeySource UserKeySource { get; set; } = new NullShortcutKeySource();

public bool ExecuteCommand(Keys key)
{
bool Resolve(IShortcutKeySource source)
{
if (source.ResolveCommand(key, out string command))
{
return CommandSource.ExecuteCommand(command);
}
return false;
}

// User, Defaultの順にトラバースしてひっかける
return Resolve(UserKeySource) || Resolve(DefaultKeySource);
}

public bool ResolveShortcutKey(string command, out Keys key)
{
return UserKeySource.ResolveShortcutKey(command, out key) || DefaultKeySource.ResolveShortcutKey(command, out key);
}
}
}

0 comments on commit cb268a9

Please sign in to comment.