// OpenTween - Client of Twitter // Copyright (c) 2015 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License // for more details. // // You should have received a copy of the GNU General public License along // with this program. If not, see , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace OpenTween { public enum FocusedControl { None, ListTab, StatusText, PostBrowser, } /// /// ショートカットキーの条件と動作を定義するクラス /// public class ShortcutCommand { private Keys[] shortcuts; private FocusedControl focusedOn; private FocusedControl notFocusedOn; private Func onlyWhen; private Func command; private bool preventDefault; /// /// ショートカットキーが動作する条件となるキー入力 /// public Keys[] Shortcuts { get { return this.shortcuts; } } /// /// ショートカットキーが動作する条件となるフォーカス状態 /// public FocusedControl FocusedOn { get { return this.focusedOn; } } /// /// ショートカットキーが動作する否定条件となるフォーカス状態 /// public FocusedControl NotFocusedOn { get { return this.notFocusedOn; } } /// /// コマンドを実行した後、コントロール既定の動作を無効化するか否か (デフォルトは true) /// public bool PreventDefault { get { return this.preventDefault; } } private ShortcutCommand() { this.shortcuts = new Keys[0]; this.command = () => Task.FromResult(0); this.onlyWhen = () => true; this.focusedOn = FocusedControl.None; this.notFocusedOn = FocusedControl.None; this.preventDefault = true; } /// /// コマンドを実行する条件を満たしているか判定します /// public bool IsMatch(Keys pressedKey, FocusedControl focusedOn) { if (!this.Shortcuts.Contains(pressedKey)) return false; if (this.FocusedOn != FocusedControl.None && this.FocusedOn != focusedOn) return false; if (this.NotFocusedOn != FocusedControl.None && this.NotFocusedOn == focusedOn) return false; if (!this.onlyWhen()) return false; return true; } /// /// コマンドを実行します /// public async Task RunCommand() { await this.command(); } /// /// 新規に ShortcutCommand インスタンスを作成するビルダーを返します /// public static ShortcutCommand.Builder Create(params Keys[] shortcuts) { return new Builder().Keys(shortcuts); } public class Builder { private readonly ShortcutCommand instance; internal Builder() { this.instance = new ShortcutCommand(); } /// /// 指定されたキーが入力された時にショートカットを発動します /// public Builder Keys(params Keys[] shortcuts) { this.instance.shortcuts = shortcuts; return this; } /// /// 指定されたコントロールにフォーカスが当たっている時のみショートカットを有効にします /// public Builder FocusedOn(FocusedControl focusedOn) { this.instance.focusedOn = focusedOn; return this; } /// /// 指定されたコントロールにフォーカスが当たっている時はショートカットを有効にしません /// public Builder NotFocusedOn(FocusedControl notFocusedOn) { this.instance.notFocusedOn = notFocusedOn; return this; } /// /// 指定された条件が true になる間のみショートカットを有効にします /// public Builder OnlyWhen(Func condition) { this.instance.onlyWhen = condition; return this; } /// /// ショートカットが入力された時に行う動作の内容 /// public ShortcutCommand Do(Action action, bool preventDefault = true) { return this.Do(SynchronousTask(action), preventDefault); } /// /// ショートカットが入力された時に行う動作の内容 /// public ShortcutCommand Do(Func action, bool preventDefault = true) { this.instance.command = action; this.instance.preventDefault = preventDefault; return this.instance; } /// 何もしないタスク private static Task noOpTask = Task.FromResult(0); /// /// Action を Func<Task> に変換します /// private static Func SynchronousTask(Action action) { return () => { action(); return noOpTask; }; } } } }