brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef CommandSet_DEFINED |
| 9 | #define CommandSet_DEFINED |
| 10 | |
| 11 | #include "SkString.h" |
| 12 | #include "Window.h" |
| 13 | |
| 14 | #include <functional> |
| 15 | |
| 16 | class SkCanvas; |
| 17 | |
| 18 | namespace sk_app { |
| 19 | |
| 20 | /** |
| 21 | * Helper class used by applications that want to hook keypresses to trigger events. |
| 22 | * |
| 23 | * An app can simply store an instance of CommandSet and then use it as follows: |
| 24 | * 1) Attach to the Window at initialization time. This registers key handlers on the window. |
| 25 | * 2) Register commands to be executed for characters or keys. Each command needs a Group and a |
| 26 | * description (both just strings). Commands attached to Keys (rather than characters) also need |
| 27 | * a displayable name for the Key. Finally, a function to execute when the key or character is |
| 28 | * pressed must be supplied. The easiest option to is pass in a lambda that captures [this] |
| 29 | * (your application object), and performs whatever action is desired. |
| 30 | * 3) At the end of your onPaint, call drawHelp, and pass in the application's canvas. |
| 31 | |
| 32 | * The CommandSet always binds 'h' to cycle through two different help screens. The first shows |
| 33 | * all commands, organized by Group (with headings for each Group). The second shows all commands |
| 34 | * alphabetically by key/character. |
| 35 | */ |
| 36 | class CommandSet { |
| 37 | public: |
| 38 | CommandSet(); |
| 39 | |
| 40 | void attach(Window* window); |
| 41 | bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers); |
| 42 | bool onChar(SkUnichar, uint32_t modifiers); |
| 43 | |
| 44 | void addCommand(SkUnichar c, const char* group, const char* description, |
| 45 | std::function<void(void)> function); |
| 46 | void addCommand(Window::Key k, const char* keyName, const char* group, const char* description, |
| 47 | std::function<void(void)> function); |
| 48 | |
| 49 | void drawHelp(SkCanvas* canvas); |
| 50 | |
| 51 | private: |
| 52 | struct Command { |
| 53 | enum CommandType { |
| 54 | kChar_CommandType, |
| 55 | kKey_CommandType, |
| 56 | }; |
| 57 | |
| 58 | Command(SkUnichar c, const char* group, const char* description, |
| 59 | std::function<void(void)> function) |
| 60 | : fType(kChar_CommandType) |
| 61 | , fChar(c) |
| 62 | , fKeyName(SkStringPrintf("%c", c)) |
| 63 | , fGroup(group) |
| 64 | , fDescription(description) |
| 65 | , fFunction(function) {} |
| 66 | |
| 67 | Command(Window::Key k, const char* keyName, const char* group, const char* description, |
| 68 | std::function<void(void)> function) |
| 69 | : fType(kKey_CommandType) |
| 70 | , fKey(k) |
| 71 | , fKeyName(keyName) |
| 72 | , fGroup(group) |
| 73 | , fDescription(description) |
| 74 | , fFunction(function) {} |
| 75 | |
| 76 | CommandType fType; |
| 77 | |
| 78 | // For kChar_CommandType |
| 79 | SkUnichar fChar; |
| 80 | |
| 81 | // For kKey_CommandType |
| 82 | Window::Key fKey; |
| 83 | |
| 84 | // Common to all command types |
| 85 | SkString fKeyName; |
| 86 | SkString fGroup; |
| 87 | SkString fDescription; |
| 88 | std::function<void(void)> fFunction; |
| 89 | }; |
| 90 | |
| 91 | static bool compareCommandKey(const Command& first, const Command& second); |
| 92 | static bool compareCommandGroup(const Command& first, const Command& second); |
| 93 | |
| 94 | enum HelpMode { |
| 95 | kNone_HelpMode, |
| 96 | kGrouped_HelpMode, |
| 97 | kAlphabetical_HelpMode, |
| 98 | }; |
| 99 | |
| 100 | Window* fWindow; |
| 101 | SkTArray<Command> fCommands; |
| 102 | HelpMode fHelpMode; |
| 103 | }; |
| 104 | |
| 105 | } // namespace sk_app |
| 106 | |
| 107 | #endif |